/**
* Copyright 2016 Hortonworks.
* <p>
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.hortonworks.registries.storage.impl.jdbc.provider.phoenix.factory;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
import com.hortonworks.registries.storage.OrderByField;
import com.hortonworks.registries.storage.Storable;
import com.hortonworks.registries.storage.StorableKey;
import com.hortonworks.registries.storage.impl.jdbc.config.ExecutionConfig;
import com.hortonworks.registries.storage.impl.jdbc.connection.ConnectionBuilder;
import com.hortonworks.registries.storage.impl.jdbc.connection.HikariCPConnectionBuilder;
import com.hortonworks.registries.storage.impl.jdbc.provider.phoenix.JdbcClient;
import com.hortonworks.registries.storage.impl.jdbc.provider.phoenix.query.PhoenixDeleteQuery;
import com.hortonworks.registries.storage.impl.jdbc.provider.phoenix.query.PhoenixSelectQuery;
import com.hortonworks.registries.storage.impl.jdbc.provider.phoenix.query.PhoenixSequenceIdQuery;
import com.hortonworks.registries.storage.impl.jdbc.provider.phoenix.query.PhoenixUpsertQuery;
import com.hortonworks.registries.storage.impl.jdbc.provider.sql.factory.AbstractQueryExecutor;
import com.hortonworks.registries.storage.impl.jdbc.provider.sql.query.SqlQuery;
import com.hortonworks.registries.storage.impl.jdbc.provider.sql.statement.PreparedStatementBuilder;
import com.hortonworks.registries.storage.impl.jdbc.util.Util;
import com.zaxxer.hikari.HikariConfig;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* SQL query executor for Phoenix.
*
* Phoenix doesn't support auto_increment feature, as well as JDBC's getGeneratedKeys().
* In order to get over, we take a workaround to {@link PhoenixSequenceIdQuery#getNextID()} which provides issuing ID
* in safe way.
*
* If the value of id is null, we issue a new ID and set ID to entity. If the value of id is not null, we just use that value.
*/
public class PhoenixExecutor extends AbstractQueryExecutor {
public PhoenixExecutor(ExecutionConfig config, ConnectionBuilder connectionBuilder) {
super(config, connectionBuilder);
}
public PhoenixExecutor(ExecutionConfig config, ConnectionBuilder connectionBuilder, CacheBuilder<SqlQuery, PreparedStatementBuilder> cacheBuilder) {
super(config, connectionBuilder, cacheBuilder);
}
@Override
public void insert(Storable storable) {
insertOrUpdate(storable);
}
@Override
public void insertOrUpdate(Storable storable) {
executeUpdate(new PhoenixUpsertQuery(storable));
}
@Override
public <T extends Storable> Collection<T> select(String namespace) {
return select(namespace, null);
}
@Override
public <T extends Storable> Collection<T> select(String namespace, List<OrderByField> orderByFields) {
return executeQuery(namespace, new PhoenixSelectQuery(namespace));
}
@Override
public <T extends Storable> Collection<T> select(StorableKey storableKey) {
return select(storableKey, null);
}
@Override
public <T extends Storable> Collection<T> select(StorableKey storableKey, List<OrderByField> orderByFields) {
return executeQuery(storableKey.getNameSpace(), new PhoenixSelectQuery(storableKey, orderByFields));
}
@Override
public void delete(StorableKey storableKey) {
executeUpdate(new PhoenixDeleteQuery(storableKey));
}
@Override
public Long nextId(String namespace) {
PhoenixSequenceIdQuery phoenixSequenceIdQuery = new PhoenixSequenceIdQuery(namespace, connectionBuilder, queryTimeoutSecs);
return phoenixSequenceIdQuery.getNextID();
}
public static PhoenixExecutor createExecutor(Map<String, Object> jdbcProps) throws Exception {
Util.validateJDBCProperties(jdbcProps, Lists.newArrayList("jdbcDriverClass", "jdbcUrl"));
String driverClassName = (String) jdbcProps.get("jdbcDriverClass");
log.info("jdbc driver class: [{}]", driverClassName);
Class.forName(driverClassName);
String jdbcUrl = (String) jdbcProps.get("jdbcUrl");
log.info("jdbc url is: [{}] ", jdbcUrl);
int queryTimeOutInSecs = -1;
if (jdbcProps.containsKey("queryTimeoutInSecs")) {
queryTimeOutInSecs = (Integer) jdbcProps.get("queryTimeoutInSecs");
if (queryTimeOutInSecs < 0) {
throw new IllegalArgumentException("queryTimeoutInSecs property can not be negative");
}
}
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl(jdbcUrl);
JdbcClient jdbcClient = new JdbcClient(jdbcUrl);
log.info("creating tables");
String createPath = "phoenix/create_tables.sql";
jdbcClient.runScript(createPath);
final HikariCPConnectionBuilder connectionBuilder = new HikariCPConnectionBuilder(hikariConfig);
final ExecutionConfig executionConfig = new ExecutionConfig(queryTimeOutInSecs);
CacheBuilder cacheBuilder = null;
if (jdbcProps.containsKey("cacheSize")) {
cacheBuilder = CacheBuilder.newBuilder().maximumSize((Integer) jdbcProps.get("cacheSize"));
}
return new PhoenixExecutor(executionConfig, connectionBuilder, cacheBuilder);
}
}