blob: f687cdb715c76f5c04a9aa2f9152f86e31d296c3 [file]
/*
* 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.phoenix.ddb;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HBaseTestingUtility;
import org.apache.phoenix.ddb.rest.RESTServer;
import org.apache.phoenix.ddb.utils.IndexBuildingActivator;
import org.apache.phoenix.end2end.ServerMetadataCacheTestImpl;
import org.apache.phoenix.jdbc.PhoenixDriver;
import org.apache.phoenix.jdbc.PhoenixTestDriver;
import org.apache.phoenix.mapreduce.index.IndexTool;
import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.ServerUtil;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.CreateGlobalSecondaryIndexAction;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.GlobalSecondaryIndexUpdate;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.Projection;
import software.amazon.awssdk.services.dynamodb.model.ProjectionType;
import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryResponse;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.awssdk.services.dynamodb.model.UpdateTableRequest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.apache.phoenix.query.BaseTest.setUpConfigForMiniCluster;
public class UpdateTable2IT {
private static final Logger LOGGER = LoggerFactory.getLogger(UpdateTable2IT.class);
private static HBaseTestingUtility utility = null;
private static String tmpDir;
private static RESTServer restServer = null;
@Rule
public final TestName testName = new TestName();
private final DynamoDbClient dynamoDbClient =
LocalDynamoDbTestBase.localDynamoDb().createV2Client();
private static DynamoDbClient phoenixDBClientV2;
private static String url;
@BeforeClass
public static void initialize() throws Exception {
tmpDir = System.getProperty("java.io.tmpdir");
LocalDynamoDbTestBase.localDynamoDb().start();
Configuration conf = HBaseConfiguration.create();
utility = new HBaseTestingUtility(conf);
setUpConfigForMiniCluster(conf);
utility.startMiniCluster();
DriverManager.registerDriver(new PhoenixTestDriver());
String zkQuorum = "localhost:" + utility.getZkCluster().getClientPort();
url = PhoenixRuntime.JDBC_PROTOCOL + PhoenixRuntime.JDBC_PROTOCOL_SEPARATOR + zkQuorum;
restServer = new RESTServer(utility.getConfiguration());
restServer.run();
LOGGER.info("started {} on port {}", restServer.getClass().getName(), restServer.getPort());
phoenixDBClientV2 = LocalDynamoDB.createV2Client("http://" + restServer.getServerAddress());
}
@AfterClass
public static void stopLocalDynamoDb() throws Exception {
LocalDynamoDbTestBase.localDynamoDb().stop();
if (restServer != null) {
restServer.stop();
}
ServerUtil.ConnectionFactory.shutdown();
try {
DriverManager.deregisterDriver(PhoenixDriver.INSTANCE);
} finally {
if (utility != null) {
utility.shutdownMiniCluster();
}
ServerMetadataCacheTestImpl.resetCache();
}
System.setProperty("java.io.tmpdir", tmpDir);
}
@Test(timeout = 120000)
public void testAsyncIndexCreationAndQuery() throws Exception {
final String tableName = "TEST_TABLE";
final String indexName = "G_IDX" + tableName;
CreateTableRequest baseTableRequest =
DDLTestUtils.getCreateTableRequest(tableName, "ForumName", ScalarAttributeType.S,
"Subject", ScalarAttributeType.S);
CreateTableRequest ddbTableRequest =
DDLTestUtils.addIndexToRequest(true, baseTableRequest, indexName, "Title",
ScalarAttributeType.S, null, null);
dynamoDbClient.createTable(ddbTableRequest);
TestUtils.waitForIndexState(dynamoDbClient, tableName, indexName, "ACTIVE");
phoenixDBClientV2.createTable(baseTableRequest);
Map<String, AttributeValue> item1 = getTestItem("Forum1", "Subject1", "Title1");
Map<String, AttributeValue> item2 = getTestItem("Forum2", "Subject2", "Title1");
Map<String, AttributeValue> item3 = getTestItem("Forum3", "Subject3", "Title2");
PutItemRequest putRequest1 = PutItemRequest.builder().tableName(tableName).item(item1).build();
PutItemRequest putRequest2 = PutItemRequest.builder().tableName(tableName).item(item2).build();
PutItemRequest putRequest3 = PutItemRequest.builder().tableName(tableName).item(item3).build();
phoenixDBClientV2.putItem(putRequest1);
phoenixDBClientV2.putItem(putRequest2);
phoenixDBClientV2.putItem(putRequest3);
dynamoDbClient.putItem(putRequest1);
dynamoDbClient.putItem(putRequest2);
dynamoDbClient.putItem(putRequest3);
UpdateTableRequest.Builder utr = UpdateTableRequest.builder().tableName(tableName);
List<GlobalSecondaryIndexUpdate> indexUpdates = new ArrayList<>();
CreateGlobalSecondaryIndexAction.Builder createIndexAction =
CreateGlobalSecondaryIndexAction.builder().indexName(indexName);
List<KeySchemaElement> idxKeySchemaElements = new ArrayList<>();
idxKeySchemaElements.add(
KeySchemaElement.builder().attributeName("Title").keyType(KeyType.HASH).build());
createIndexAction.keySchema(idxKeySchemaElements);
createIndexAction.projection(
Projection.builder().projectionType(ProjectionType.ALL).build());
createIndexAction.provisionedThroughput(
ProvisionedThroughput.builder().readCapacityUnits(50L).writeCapacityUnits(50L).build());
GlobalSecondaryIndexUpdate indexUpdate = GlobalSecondaryIndexUpdate.builder()
.create(createIndexAction.build()).build();
indexUpdates.add(indexUpdate);
utr.globalSecondaryIndexUpdates(indexUpdates);
List<AttributeDefinition> attrDefs =
new ArrayList<>(baseTableRequest.attributeDefinitions());
attrDefs.add(AttributeDefinition.builder().attributeName("Title")
.attributeType(ScalarAttributeType.S).build());
utr.attributeDefinitions(attrDefs);
phoenixDBClientV2.updateTable(utr.build());
try (Connection connection = DriverManager.getConnection(url)) {
// background thread activates index to BUILDING state
IndexBuildingActivator.activateIndexesForBuilding(connection, 0);
// run MR tool to build index and set state to ACTIVE
Configuration conf = new Configuration(utility.getConfiguration());
TestUtils.runIndexTool(conf, false, "DDB", tableName, tableName + "_" + indexName, null, 0, IndexTool.IndexVerifyType.NONE, IndexTool.IndexDisableLoggingType.NONE);
}
// make sure Index is active
TestUtils.waitForIndexState(phoenixDBClientV2, tableName, indexName, "ACTIVE");
Map<String, AttributeValue> item4 = getTestItem("Forum4", "Subject4", "Title2");
Map<String, AttributeValue> item5 = getTestItem("Forum5", "Subject5", "Title2");
Map<String, AttributeValue> item6 = getTestItem("Forum6", "Subject6", "Title1");
PutItemRequest putRequest4 = PutItemRequest.builder().tableName(tableName).item(item4).build();
PutItemRequest putRequest5 = PutItemRequest.builder().tableName(tableName).item(item5).build();
PutItemRequest putRequest6 = PutItemRequest.builder().tableName(tableName).item(item6).build();
phoenixDBClientV2.putItem(putRequest4);
phoenixDBClientV2.putItem(putRequest5);
phoenixDBClientV2.putItem(putRequest6);
dynamoDbClient.putItem(putRequest4);
dynamoDbClient.putItem(putRequest5);
dynamoDbClient.putItem(putRequest6);
QueryRequest.Builder qr = QueryRequest.builder().tableName(tableName);
qr.indexName(indexName);
qr.keyConditionExpression("#0 = :v0");
Map<String, String> exprAttrNames = new HashMap<>();
exprAttrNames.put("#0", "Title");
qr.expressionAttributeNames(exprAttrNames);
Map<String, AttributeValue> exprAttrVal = new HashMap<>();
exprAttrVal.put(":v0", AttributeValue.builder().s("Title1").build());
qr.expressionAttributeValues(exprAttrVal);
QueryResponse phoenixResult = phoenixDBClientV2.query(qr.build());
QueryResponse dynamoResult = dynamoDbClient.query(qr.build());
Assert.assertEquals(dynamoResult.count(), phoenixResult.count());
ItemComparator.areItemsEqual(dynamoResult.items(), phoenixResult.items());
TestUtils.validateIndexUsed(qr.build(), url);
}
private Map<String, AttributeValue> getTestItem(String forumName, String subject, String title) {
Map<String, AttributeValue> item = new HashMap<>();
item.put("ForumName", AttributeValue.builder().s(forumName).build());
item.put("Subject", AttributeValue.builder().s(subject).build());
item.put("Title", AttributeValue.builder().s(title).build());
return item;
}
}