/*
* Licensed 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 com.facebook.presto.raptor.metadata;
import com.facebook.presto.metadata.MetadataUtil.TableMetadataBuilder;
import com.facebook.presto.raptor.NodeSupplier;
import com.facebook.presto.raptor.RaptorColumnHandle;
import com.facebook.presto.raptor.RaptorColumnIdentity;
import com.facebook.presto.raptor.RaptorConnectorId;
import com.facebook.presto.raptor.RaptorMetadata;
import com.facebook.presto.raptor.RaptorPartitioningHandle;
import com.facebook.presto.raptor.RaptorSessionProperties;
import com.facebook.presto.raptor.RaptorTableHandle;
import com.facebook.presto.raptor.RaptorTableIdentity;
import com.facebook.presto.raptor.storage.StorageManagerConfig;
import com.facebook.presto.spi.ColumnHandle;
import com.facebook.presto.spi.ColumnIdentity;
import com.facebook.presto.spi.ColumnMetadata;
import com.facebook.presto.spi.ConnectorInsertTableHandle;
import com.facebook.presto.spi.ConnectorNewTableLayout;
import com.facebook.presto.spi.ConnectorOutputTableHandle;
import com.facebook.presto.spi.ConnectorSession;
import com.facebook.presto.spi.ConnectorTableHandle;
import com.facebook.presto.spi.ConnectorTableMetadata;
import com.facebook.presto.spi.ConnectorViewDefinition;
import com.facebook.presto.spi.NodeManager;
import com.facebook.presto.spi.PrestoException;
import com.facebook.presto.spi.SchemaTableName;
import com.facebook.presto.spi.SchemaTablePrefix;
import com.facebook.presto.spi.TableIdentity;
import com.facebook.presto.testing.TestingConnectorSession;
import com.facebook.presto.testing.TestingNodeManager;
import com.facebook.presto.type.TypeRegistry;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.ByteArrayDataOutput;
import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.Handle;
import org.skife.jdbi.v2.util.BooleanMapper;
import org.skife.jdbi.v2.util.LongMapper;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.stream.Collectors;
import static com.facebook.presto.metadata.MetadataUtil.TableMetadataBuilder.tableMetadataBuilder;
import static com.facebook.presto.raptor.RaptorTableProperties.BUCKETED_ON_PROPERTY;
import static com.facebook.presto.raptor.RaptorTableProperties.BUCKET_COUNT_PROPERTY;
import static com.facebook.presto.raptor.RaptorTableProperties.DISTRIBUTION_NAME_PROPERTY;
import static com.facebook.presto.raptor.RaptorTableProperties.ORDERING_PROPERTY;
import static com.facebook.presto.raptor.RaptorTableProperties.ORGANIZED_PROPERTY;
import static com.facebook.presto.raptor.RaptorTableProperties.TEMPORAL_COLUMN_PROPERTY;
import static com.facebook.presto.raptor.metadata.SchemaDaoUtil.createTablesWithRetry;
import static com.facebook.presto.raptor.metadata.TestDatabaseShardManager.createShardManager;
import static com.facebook.presto.spi.StandardErrorCode.TRANSACTION_CONFLICT;
import static com.facebook.presto.spi.type.BigintType.BIGINT;
import static com.facebook.presto.spi.type.DateType.DATE;
import static com.facebook.presto.spi.type.DoubleType.DOUBLE;
import static com.google.common.base.Ticker.systemTicker;
import static com.google.common.io.ByteStreams.newDataOutput;
import static io.airlift.testing.Assertions.assertEqualsIgnoreOrder;
import static io.airlift.testing.Assertions.assertInstanceOf;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
@Test(singleThreaded = true)
public class TestRaptorMetadata
{
private static final SchemaTableName DEFAULT_TEST_ORDERS = new SchemaTableName("test", "orders");
private static final SchemaTableName DEFAULT_TEST_LINEITEMS = new SchemaTableName("test", "lineitems");
private static final ConnectorSession SESSION = new TestingConnectorSession(
new RaptorSessionProperties(new StorageManagerConfig()).getSessionProperties());
private DBI dbi;
private Handle dummyHandle;
private ShardManager shardManager;
private RaptorMetadata metadata;
@BeforeMethod
public void setupDatabase()
throws Exception
{
TypeRegistry typeRegistry = new TypeRegistry();
dbi = new DBI("jdbc:h2:mem:test" + System.nanoTime());
dbi.registerMapper(new TableColumn.Mapper(typeRegistry));
dbi.registerMapper(new Distribution.Mapper(typeRegistry));
dummyHandle = dbi.open();
createTablesWithRetry(dbi);
RaptorConnectorId connectorId = new RaptorConnectorId("raptor");
NodeManager nodeManager = new TestingNodeManager();
NodeSupplier nodeSupplier = nodeManager::getWorkerNodes;
shardManager = createShardManager(dbi, nodeSupplier, systemTicker());
metadata = new RaptorMetadata(connectorId.toString(), dbi, shardManager);
}
@AfterMethod(alwaysRun = true)
public void cleanupDatabase()
{
dummyHandle.close();
}
@Test
public void testRenameColumn()
throws Exception
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
metadata.createTable(SESSION, getOrdersTable());
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
assertInstanceOf(tableHandle, RaptorTableHandle.class);
RaptorTableHandle raptorTableHandle = (RaptorTableHandle) tableHandle;
ColumnHandle columnHandle = metadata.getColumnHandles(SESSION, tableHandle).get("orderkey");
metadata.renameColumn(SESSION, raptorTableHandle, columnHandle, "orderkey_renamed");
assertNull(metadata.getColumnHandles(SESSION, tableHandle).get("orderkey"));
assertNotNull(metadata.getColumnHandles(SESSION, tableHandle).get("orderkey_renamed"));
}
@Test
public void testRenameTable()
throws Exception
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
metadata.createTable(SESSION, getOrdersTable());
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
assertInstanceOf(tableHandle, RaptorTableHandle.class);
RaptorTableHandle raptorTableHandle = (RaptorTableHandle) tableHandle;
SchemaTableName renamedTable = new SchemaTableName(raptorTableHandle.getSchemaName(), "orders_renamed");
metadata.renameTable(SESSION, raptorTableHandle, renamedTable);
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
ConnectorTableHandle renamedTableHandle = metadata.getTableHandle(SESSION, renamedTable);
assertNotNull(renamedTableHandle);
assertEquals(((RaptorTableHandle) renamedTableHandle).getTableName(), renamedTable.getTableName());
}
@Test
public void testCreateTable()
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
metadata.createTable(SESSION, getOrdersTable());
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
assertInstanceOf(tableHandle, RaptorTableHandle.class);
assertEquals(((RaptorTableHandle) tableHandle).getTableId(), 1);
ConnectorTableMetadata table = metadata.getTableMetadata(SESSION, tableHandle);
assertTableEqual(table, getOrdersTable());
ColumnHandle columnHandle = metadata.getColumnHandles(SESSION, tableHandle).get("orderkey");
assertInstanceOf(columnHandle, RaptorColumnHandle.class);
assertEquals(((RaptorColumnHandle) columnHandle).getColumnId(), 1);
ColumnMetadata columnMetadata = metadata.getColumnMetadata(SESSION, tableHandle, columnHandle);
assertNotNull(columnMetadata);
assertEquals(columnMetadata.getName(), "orderkey");
assertEquals(columnMetadata.getType(), BIGINT);
}
@Test
public void testTableProperties()
throws Exception
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
ConnectorTableMetadata ordersTable = getOrdersTable(ImmutableMap.of(
ORDERING_PROPERTY, ImmutableList.of("orderdate", "custkey"),
TEMPORAL_COLUMN_PROPERTY, "orderdate"));
metadata.createTable(SESSION, ordersTable);
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
assertInstanceOf(tableHandle, RaptorTableHandle.class);
RaptorTableHandle raptorTableHandle = (RaptorTableHandle) tableHandle;
assertEquals(raptorTableHandle.getTableId(), 1);
long tableId = raptorTableHandle.getTableId();
MetadataDao metadataDao = dbi.onDemand(MetadataDao.class);
// verify sort columns
List<TableColumn> sortColumns = metadataDao.listSortColumns(tableId);
assertTableColumnsEqual(sortColumns, ImmutableList.of(
new TableColumn(DEFAULT_TEST_ORDERS, "orderdate", DATE, 4, OptionalInt.empty(), OptionalInt.of(0), true),
new TableColumn(DEFAULT_TEST_ORDERS, "custkey", BIGINT, 2, OptionalInt.empty(), OptionalInt.of(1), false)));
// verify temporal column
assertEquals(metadataDao.getTemporalColumnId(tableId), Long.valueOf(4));
// verify no organization
assertFalse(metadataDao.getTableInformation(tableId).isOrganized());
metadata.dropTable(SESSION, tableHandle);
}
@Test
public void testTablePropertiesWithOrganization()
throws Exception
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
ConnectorTableMetadata ordersTable = getOrdersTable(ImmutableMap.of(
ORDERING_PROPERTY, ImmutableList.of("orderdate", "custkey"),
ORGANIZED_PROPERTY, true));
metadata.createTable(SESSION, ordersTable);
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
assertInstanceOf(tableHandle, RaptorTableHandle.class);
RaptorTableHandle raptorTableHandle = (RaptorTableHandle) tableHandle;
assertEquals(raptorTableHandle.getTableId(), 1);
long tableId = raptorTableHandle.getTableId();
MetadataDao metadataDao = dbi.onDemand(MetadataDao.class);
// verify sort columns
List<TableColumn> sortColumns = metadataDao.listSortColumns(tableId);
assertTableColumnsEqual(sortColumns, ImmutableList.of(
new TableColumn(DEFAULT_TEST_ORDERS, "orderdate", DATE, 4, OptionalInt.empty(), OptionalInt.of(0), false),
new TableColumn(DEFAULT_TEST_ORDERS, "custkey", BIGINT, 2, OptionalInt.empty(), OptionalInt.of(1), false)));
// verify organization
assertTrue(metadataDao.getTableInformation(tableId).isOrganized());
metadata.dropTable(SESSION, tableHandle);
}
@Test
public void testCreateBucketedTable()
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
ConnectorTableMetadata ordersTable = getOrdersTable(ImmutableMap.of(
BUCKET_COUNT_PROPERTY, 16,
BUCKETED_ON_PROPERTY, ImmutableList.of("custkey", "orderkey")));
metadata.createTable(SESSION, ordersTable);
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
assertInstanceOf(tableHandle, RaptorTableHandle.class);
RaptorTableHandle raptorTableHandle = (RaptorTableHandle) tableHandle;
assertEquals(raptorTableHandle.getTableId(), 1);
long tableId = raptorTableHandle.getTableId();
MetadataDao metadataDao = dbi.onDemand(MetadataDao.class);
assertTableColumnsEqual(metadataDao.listBucketColumns(tableId), ImmutableList.of(
new TableColumn(DEFAULT_TEST_ORDERS, "custkey", BIGINT, 2, OptionalInt.of(0), OptionalInt.empty(), false),
new TableColumn(DEFAULT_TEST_ORDERS, "orderkey", BIGINT, 1, OptionalInt.of(1), OptionalInt.empty(), false)));
assertEquals(raptorTableHandle.getBucketCount(), OptionalInt.of(16));
assertEquals(getTableDistributionId(tableId), Long.valueOf(1));
metadata.dropTable(SESSION, tableHandle);
// create a new table and verify it has a different distribution
metadata.createTable(SESSION, ordersTable);
tableId = ((RaptorTableHandle) metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS)).getTableId();
assertEquals(tableId, 2);
assertEquals(getTableDistributionId(tableId), Long.valueOf(2));
}
@Test
public void testCreateBucketedTableAsSelect()
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
ConnectorTableMetadata ordersTable = getOrdersTable(ImmutableMap.of(
BUCKET_COUNT_PROPERTY, 32,
BUCKETED_ON_PROPERTY, ImmutableList.of("orderkey", "custkey")));
ConnectorNewTableLayout layout = metadata.getNewTableLayout(SESSION, ordersTable).get();
assertEquals(layout.getPartitionColumns(), ImmutableList.of("orderkey", "custkey"));
assertInstanceOf(layout.getPartitioning(), RaptorPartitioningHandle.class);
RaptorPartitioningHandle partitioning = (RaptorPartitioningHandle) layout.getPartitioning();
assertEquals(partitioning.getDistributionId(), 1);
ConnectorOutputTableHandle outputHandle = metadata.beginCreateTable(SESSION, ordersTable, Optional.of(layout));
metadata.finishCreateTable(SESSION, outputHandle, ImmutableList.of());
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
assertInstanceOf(tableHandle, RaptorTableHandle.class);
RaptorTableHandle raptorTableHandle = (RaptorTableHandle) tableHandle;
assertEquals(raptorTableHandle.getTableId(), 1);
long tableId = raptorTableHandle.getTableId();
MetadataDao metadataDao = dbi.onDemand(MetadataDao.class);
assertTableColumnsEqual(metadataDao.listBucketColumns(tableId), ImmutableList.of(
new TableColumn(DEFAULT_TEST_ORDERS, "orderkey", BIGINT, 1, OptionalInt.of(0), OptionalInt.empty(), false),
new TableColumn(DEFAULT_TEST_ORDERS, "custkey", BIGINT, 2, OptionalInt.of(1), OptionalInt.empty(), false)));
assertEquals(raptorTableHandle.getBucketCount(), OptionalInt.of(32));
assertEquals(getTableDistributionId(tableId), Long.valueOf(1));
metadata.dropTable(SESSION, tableHandle);
}
@Test
public void testCreateBucketedTableExistingDistribution()
{
MetadataDao metadataDao = dbi.onDemand(MetadataDao.class);
// create orders table
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
ConnectorTableMetadata table = getOrdersTable(ImmutableMap.of(
BUCKET_COUNT_PROPERTY, 16,
BUCKETED_ON_PROPERTY, ImmutableList.of("orderkey"),
DISTRIBUTION_NAME_PROPERTY, "orders"));
metadata.createTable(SESSION, table);
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
assertInstanceOf(tableHandle, RaptorTableHandle.class);
RaptorTableHandle raptorTableHandle = (RaptorTableHandle) tableHandle;
long tableId = raptorTableHandle.getTableId();
assertEquals(raptorTableHandle.getTableId(), 1);
assertTableColumnsEqual(metadataDao.listBucketColumns(tableId), ImmutableList.of(
new TableColumn(DEFAULT_TEST_ORDERS, "orderkey", BIGINT, 1, OptionalInt.of(0), OptionalInt.empty(), false)));
assertEquals(raptorTableHandle.getBucketCount(), OptionalInt.of(16));
assertEquals(getTableDistributionId(tableId), Long.valueOf(1));
// create lineitems table
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_LINEITEMS));
table = getLineItemsTable(ImmutableMap.of(
BUCKET_COUNT_PROPERTY, 16,
BUCKETED_ON_PROPERTY, ImmutableList.of("orderkey"),
DISTRIBUTION_NAME_PROPERTY, "orders"));
metadata.createTable(SESSION, table);
tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_LINEITEMS);
assertInstanceOf(tableHandle, RaptorTableHandle.class);
raptorTableHandle = (RaptorTableHandle) tableHandle;
tableId = raptorTableHandle.getTableId();
assertEquals(tableId, 2);
assertTableColumnsEqual(metadataDao.listBucketColumns(tableId), ImmutableList.of(
new TableColumn(DEFAULT_TEST_LINEITEMS, "orderkey", BIGINT, 1, OptionalInt.of(0), OptionalInt.empty(), false)));
assertEquals(raptorTableHandle.getBucketCount(), OptionalInt.of(16));
assertEquals(getTableDistributionId(tableId), Long.valueOf(1));
}
@Test(expectedExceptions = PrestoException.class, expectedExceptionsMessageRegExp = "Ordering column does not exist: orderdatefoo")
public void testInvalidOrderingColumns()
throws Exception
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
ConnectorTableMetadata ordersTable = getOrdersTable(ImmutableMap.of(ORDERING_PROPERTY, ImmutableList.of("orderdatefoo")));
metadata.createTable(SESSION, ordersTable);
fail("Expected createTable to fail");
}
@Test(expectedExceptions = PrestoException.class, expectedExceptionsMessageRegExp = "Temporal column does not exist: foo")
public void testInvalidTemporalColumn()
throws Exception
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
ConnectorTableMetadata ordersTable = getOrdersTable(ImmutableMap.of(TEMPORAL_COLUMN_PROPERTY, "foo"));
metadata.createTable(SESSION, ordersTable);
fail("Expected createTable to fail");
}
@Test(expectedExceptions = PrestoException.class, expectedExceptionsMessageRegExp = "Temporal column must be of type timestamp or date: orderkey")
public void testInvalidTemporalColumnType()
throws Exception
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
metadata.createTable(SESSION, getOrdersTable(ImmutableMap.of(TEMPORAL_COLUMN_PROPERTY, "orderkey")));
}
@Test(expectedExceptions = PrestoException.class, expectedExceptionsMessageRegExp = "Table with temporal columns cannot be organized")
public void testInvalidTemporalOrganization()
throws Exception
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
metadata.createTable(SESSION, getOrdersTable(ImmutableMap.of(
TEMPORAL_COLUMN_PROPERTY, "orderdate",
ORGANIZED_PROPERTY, true)));
}
@Test(expectedExceptions = PrestoException.class, expectedExceptionsMessageRegExp = "Table organization requires an ordering")
public void testInvalidOrderingOrganization()
throws Exception
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
metadata.createTable(SESSION, getOrdersTable(ImmutableMap.of(ORGANIZED_PROPERTY, true)));
}
@Test
public void testSortOrderProperty()
throws Exception
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
ConnectorTableMetadata ordersTable = getOrdersTable(ImmutableMap.of(ORDERING_PROPERTY, ImmutableList.of("orderdate", "custkey")));
metadata.createTable(SESSION, ordersTable);
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
assertInstanceOf(tableHandle, RaptorTableHandle.class);
RaptorTableHandle raptorTableHandle = (RaptorTableHandle) tableHandle;
assertEquals(raptorTableHandle.getTableId(), 1);
long tableId = raptorTableHandle.getTableId();
MetadataDao metadataDao = dbi.onDemand(MetadataDao.class);
// verify sort columns
List<TableColumn> sortColumns = metadataDao.listSortColumns(tableId);
assertTableColumnsEqual(sortColumns, ImmutableList.of(
new TableColumn(DEFAULT_TEST_ORDERS, "orderdate", DATE, 4, OptionalInt.empty(), OptionalInt.of(0), false),
new TableColumn(DEFAULT_TEST_ORDERS, "custkey", BIGINT, 2, OptionalInt.empty(), OptionalInt.of(1), false)));
// verify temporal column is not set
assertEquals(metadataDao.getTemporalColumnId(tableId), null);
metadata.dropTable(SESSION, tableHandle);
}
@Test
public void testTemporalColumn()
throws Exception
{
assertNull(metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS));
ConnectorTableMetadata ordersTable = getOrdersTable(ImmutableMap.of(TEMPORAL_COLUMN_PROPERTY, "orderdate"));
metadata.createTable(SESSION, ordersTable);
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
assertInstanceOf(tableHandle, RaptorTableHandle.class);
RaptorTableHandle raptorTableHandle = (RaptorTableHandle) tableHandle;
assertEquals(raptorTableHandle.getTableId(), 1);
long tableId = raptorTableHandle.getTableId();
MetadataDao metadataDao = dbi.onDemand(MetadataDao.class);
// verify sort columns are not set
List<TableColumn> sortColumns = metadataDao.listSortColumns(tableId);
assertEquals(sortColumns.size(), 0);
assertEquals(sortColumns, ImmutableList.of());
// verify temporal column is set
assertEquals(metadataDao.getTemporalColumnId(tableId), Long.valueOf(4));
metadata.dropTable(SESSION, tableHandle);
}
@Test
public void testListTables()
{
metadata.createTable(SESSION, getOrdersTable());
List<SchemaTableName> tables = metadata.listTables(SESSION, null);
assertEquals(tables, ImmutableList.of(DEFAULT_TEST_ORDERS));
}
@Test
public void testListTableColumns()
{
metadata.createTable(SESSION, getOrdersTable());
Map<SchemaTableName, List<ColumnMetadata>> columns = metadata.listTableColumns(SESSION, new SchemaTablePrefix());
assertEquals(columns, ImmutableMap.of(DEFAULT_TEST_ORDERS, getOrdersTable().getColumns()));
}
@Test
public void testListTableColumnsFiltering()
{
metadata.createTable(SESSION, getOrdersTable());
Map<SchemaTableName, List<ColumnMetadata>> filterCatalog = metadata.listTableColumns(SESSION, new SchemaTablePrefix());
Map<SchemaTableName, List<ColumnMetadata>> filterSchema = metadata.listTableColumns(SESSION, new SchemaTablePrefix("test"));
Map<SchemaTableName, List<ColumnMetadata>> filterTable = metadata.listTableColumns(SESSION, new SchemaTablePrefix("test", "orders"));
assertEquals(filterCatalog, filterSchema);
assertEquals(filterCatalog, filterTable);
}
@Test
public void testTableIdentity()
throws Exception
{
// Test TableIdentity round trip.
metadata.createTable(SESSION, getOrdersTable());
ConnectorTableHandle connectorTableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
TableIdentity tableIdentity = metadata.getTableIdentity(connectorTableHandle);
byte[] bytes = tableIdentity.serialize();
assertEquals(tableIdentity, metadata.deserializeTableIdentity(bytes));
// Test one hard coded serialized data for each version.
byte version = 1;
long tableId = 12345678L;
ByteArrayDataOutput dataOutput = newDataOutput();
dataOutput.writeByte(version);
dataOutput.writeLong(tableId);
byte[] testBytes = dataOutput.toByteArray();
TableIdentity testTableIdentity = metadata.deserializeTableIdentity(testBytes);
assertEquals(testTableIdentity, new RaptorTableIdentity(tableId));
}
@Test
public void testColumnIdentity()
throws Exception
{
// Test ColumnIdentity round trip.
metadata.createTable(SESSION, getOrdersTable());
ConnectorTableHandle connectorTableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
Map<String, ColumnHandle> columnHandles = metadata.getColumnHandles(SESSION, connectorTableHandle);
ColumnIdentity orderKeyColumnIdentity = metadata.getColumnIdentity(columnHandles.get("orderkey"));
byte[] bytes = orderKeyColumnIdentity.serialize();
assertEquals(orderKeyColumnIdentity, metadata.deserializeColumnIdentity(bytes));
// Test one hard coded serialized data for each version.
byte version = 1;
long columnId = 123456789012L;
ByteArrayDataOutput dataOutput = newDataOutput();
dataOutput.writeByte(version);
dataOutput.writeLong(columnId);
byte[] testBytes = dataOutput.toByteArray();
ColumnIdentity testColumnIdentity = metadata.deserializeColumnIdentity(testBytes);
assertEquals(testColumnIdentity, new RaptorColumnIdentity(columnId));
}
@Test
public void testViews()
{
SchemaTableName test1 = new SchemaTableName("test", "test_view1");
SchemaTableName test2 = new SchemaTableName("test", "test_view2");
// create views
metadata.createView(SESSION, test1, "test1", false);
metadata.createView(SESSION, test2, "test2", false);
// verify listing
List<SchemaTableName> list = metadata.listViews(SESSION, "test");
assertEqualsIgnoreOrder(list, ImmutableList.of(test1, test2));
// verify getting data
Map<SchemaTableName, ConnectorViewDefinition> views = metadata.getViews(SESSION, new SchemaTablePrefix("test"));
assertEquals(views.keySet(), ImmutableSet.of(test1, test2));
assertEquals(views.get(test1).getViewData(), "test1");
assertEquals(views.get(test2).getViewData(), "test2");
// drop first view
metadata.dropView(SESSION, test1);
views = metadata.getViews(SESSION, new SchemaTablePrefix("test"));
assertEquals(views.keySet(), ImmutableSet.of(test2));
// drop second view
metadata.dropView(SESSION, test2);
views = metadata.getViews(SESSION, new SchemaTablePrefix("test"));
assertTrue(views.isEmpty());
// verify listing everything
views = metadata.getViews(SESSION, new SchemaTablePrefix());
assertTrue(views.isEmpty());
}
@Test(expectedExceptions = PrestoException.class, expectedExceptionsMessageRegExp = "View already exists: test\\.test_view")
public void testCreateViewWithoutReplace()
{
SchemaTableName test = new SchemaTableName("test", "test_view");
try {
metadata.createView(SESSION, test, "test", false);
}
catch (Exception e) {
fail("should have succeeded");
}
metadata.createView(SESSION, test, "test", false);
}
@Test
public void testCreateViewWithReplace()
{
SchemaTableName test = new SchemaTableName("test", "test_view");
metadata.createView(SESSION, test, "aaa", true);
metadata.createView(SESSION, test, "bbb", true);
assertEquals(metadata.getViews(SESSION, test.toSchemaTablePrefix()).get(test).getViewData(), "bbb");
}
@Test
public void testTransactionSelect()
throws Exception
{
metadata.createTable(SESSION, getOrdersTable());
// reads do not create a transaction
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
assertInstanceOf(tableHandle, RaptorTableHandle.class);
assertFalse(((RaptorTableHandle) tableHandle).getTransactionId().isPresent());
}
@Test
public void testTransactionTableWrite()
throws Exception
{
// start table creation
long transactionId = 1;
ConnectorOutputTableHandle outputHandle = metadata.beginCreateTable(SESSION, getOrdersTable(), Optional.empty());
// transaction is in progress
assertTrue(transactionExists(transactionId));
assertNull(transactionSuccessful(transactionId));
// commit table creation
metadata.finishCreateTable(SESSION, outputHandle, ImmutableList.of());
assertTrue(transactionExists(transactionId));
assertTrue(transactionSuccessful(transactionId));
}
@Test
public void testTransactionInsert()
throws Exception
{
// creating a table allocates a transaction
long transactionId = 1;
metadata.createTable(SESSION, getOrdersTable());
assertTrue(transactionSuccessful(transactionId));
// start insert
transactionId++;
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
ConnectorInsertTableHandle insertHandle = metadata.beginInsert(SESSION, tableHandle);
// transaction is in progress
assertTrue(transactionExists(transactionId));
assertNull(transactionSuccessful(transactionId));
// commit insert
metadata.finishInsert(SESSION, insertHandle, ImmutableList.of());
assertTrue(transactionExists(transactionId));
assertTrue(transactionSuccessful(transactionId));
}
@Test
public void testTransactionDelete()
throws Exception
{
// creating a table allocates a transaction
long transactionId = 1;
metadata.createTable(SESSION, getOrdersTable());
assertTrue(transactionSuccessful(transactionId));
// start delete
transactionId++;
ConnectorTableHandle tableHandle = metadata.getTableHandle(SESSION, DEFAULT_TEST_ORDERS);
tableHandle = metadata.beginDelete(SESSION, tableHandle);
// verify transaction is assigned for deletion handle
assertInstanceOf(tableHandle, RaptorTableHandle.class);
RaptorTableHandle raptorTableHandle = (RaptorTableHandle) tableHandle;
assertEquals(raptorTableHandle.getTableId(), 1);
assertEquals(raptorTableHandle.getTransactionId(), OptionalLong.of(transactionId));
// transaction is in progress
assertTrue(transactionExists(transactionId));
assertNull(transactionSuccessful(transactionId));
// rollback delete
metadata.rollback();
assertTrue(transactionExists(transactionId));
assertFalse(transactionSuccessful(transactionId));
// start another delete
transactionId++;
tableHandle = metadata.beginDelete(SESSION, tableHandle);
// transaction is in progress
assertTrue(transactionExists(transactionId));
assertNull(transactionSuccessful(transactionId));
// commit delete
metadata.finishDelete(SESSION, tableHandle, ImmutableList.of());
assertTrue(transactionExists(transactionId));
assertTrue(transactionSuccessful(transactionId));
}
@Test
public void testTransactionAbort()
throws Exception
{
// start table creation
long transactionId = 1;
ConnectorOutputTableHandle outputHandle = metadata.beginCreateTable(SESSION, getOrdersTable(), Optional.empty());
// transaction is in progress
assertTrue(transactionExists(transactionId));
assertNull(transactionSuccessful(transactionId));
// force transaction to abort
shardManager.rollbackTransaction(transactionId);
assertTrue(transactionExists(transactionId));
assertFalse(transactionSuccessful(transactionId));
// commit table creation
try {
metadata.finishCreateTable(SESSION, outputHandle, ImmutableList.of());
fail("expected exception");
}
catch (PrestoException e) {
assertEquals(e.getErrorCode(), TRANSACTION_CONFLICT.toErrorCode());
}
}
private boolean transactionExists(long transactionId)
{
try (Handle handle = dbi.open()) {
return handle
.createQuery("SELECT count(*) FROM transactions WHERE transaction_id = ?")
.bind(0, transactionId)
.map(BooleanMapper.FIRST)
.first();
}
}
private Boolean transactionSuccessful(long transactionId)
{
try (Handle handle = dbi.open()) {
return (Boolean) handle
.createQuery("SELECT successful FROM transactions WHERE transaction_id = ?")
.bind(0, transactionId)
.first()
.get("successful");
}
}
private Long getTableDistributionId(long tableId)
{
try (Handle handle = dbi.open()) {
return handle.createQuery("SELECT distribution_id FROM tables WHERE table_id = ?")
.bind(0, tableId)
.map(LongMapper.FIRST)
.first();
}
}
private static ConnectorTableMetadata getOrdersTable()
{
return getOrdersTable(ImmutableMap.of());
}
private static ConnectorTableMetadata getOrdersTable(Map<String, Object> properties)
{
return buildTable(properties, tableMetadataBuilder(DEFAULT_TEST_ORDERS)
.column("orderkey", BIGINT)
.column("custkey", BIGINT)
.column("totalprice", DOUBLE)
.column("orderdate", DATE));
}
private static ConnectorTableMetadata getLineItemsTable(Map<String, Object> properties)
{
return buildTable(properties, tableMetadataBuilder(DEFAULT_TEST_LINEITEMS)
.column("orderkey", BIGINT)
.column("partkey", BIGINT)
.column("quantity", DOUBLE)
.column("price", DOUBLE));
}
private static ConnectorTableMetadata buildTable(Map<String, Object> properties, TableMetadataBuilder builder)
{
if (!properties.isEmpty()) {
for (Map.Entry<String, Object> entry : properties.entrySet()) {
builder.property(entry.getKey(), entry.getValue());
}
}
return builder.build();
}
private static void assertTableEqual(ConnectorTableMetadata actual, ConnectorTableMetadata expected)
{
assertEquals(actual.getTable(), expected.getTable());
List<ColumnMetadata> actualColumns = actual.getColumns().stream()
.filter(columnMetadata -> !columnMetadata.isHidden())
.collect(Collectors.toList());
List<ColumnMetadata> expectedColumns = expected.getColumns();
assertEquals(actualColumns.size(), expectedColumns.size());
for (int i = 0; i < actualColumns.size(); i++) {
ColumnMetadata actualColumn = actualColumns.get(i);
ColumnMetadata expectedColumn = expectedColumns.get(i);
assertEquals(actualColumn.getName(), expectedColumn.getName());
assertEquals(actualColumn.getType(), expectedColumn.getType());
}
assertEquals(actual.getProperties(), expected.getProperties());
}
private static void assertTableColumnEqual(TableColumn actual, TableColumn expected)
{
assertEquals(actual.getTable(), expected.getTable());
assertEquals(actual.getColumnId(), expected.getColumnId());
assertEquals(actual.getColumnName(), expected.getColumnName());
assertEquals(actual.getDataType(), expected.getDataType());
assertEquals(actual.getBucketOrdinal(), expected.getBucketOrdinal());
assertEquals(actual.getSortOrdinal(), expected.getSortOrdinal());
assertEquals(actual.isTemporal(), expected.isTemporal());
}
private static void assertTableColumnsEqual(List<TableColumn> actual, List<TableColumn> expected)
{
assertEquals(actual.size(), expected.size());
for (int i = 0; i < actual.size(); i++) {
assertTableColumnEqual(actual.get(i), expected.get(i));
}
}
}