/*******************************************************************************
* Copyright 2016, 2017 Capital One Services, LLC and Bitwise, Inc.
* 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 hydrograph.server.metadata.strategy;
import hydrograph.server.metadata.entity.TableEntity;
import hydrograph.server.metadata.entity.TableSchemaFieldEntity;
import hydrograph.server.metadata.exception.ParamsCannotBeNullOrEmpty;
import hydrograph.server.metadata.strategy.base.MetadataStrategyTemplate;
import hydrograph.server.utilities.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Concrete implementation for RedShift database and getting the table entity
* parameters.
*/
public class RedshiftMetadataStrategy extends MetadataStrategyTemplate {
Logger LOG = LoggerFactory.getLogger(RedshiftMetadataStrategy.class);
Connection connection = null;
private String query = null, tableName = null;
/**
* Used to set the connection for RedShift
*
* @param connectionProperties
* - contain request params details
* @throws ClassNotFoundException
* @throws SQLException
*/
@SuppressWarnings("unchecked")
@Override
public void setConnection(Map connectionProperties) throws ClassNotFoundException, SQLException {
String host = connectionProperties
.getOrDefault(Constants.HOST_NAME,
new ParamsCannotBeNullOrEmpty(Constants.HOST_NAME + " not found in request parameter"))
.toString();
String port = connectionProperties
.getOrDefault(Constants.PORT_NUMBER,
new ParamsCannotBeNullOrEmpty(Constants.PORT_NUMBER + " not found in request parameter"))
.toString();
String userId = connectionProperties
.getOrDefault(Constants.USERNAME,
new ParamsCannotBeNullOrEmpty(Constants.USERNAME + " not found in request parameter"))
.toString();
String service_pwd = connectionProperties
.getOrDefault(Constants.SERVICE_PWD,
new ParamsCannotBeNullOrEmpty(Constants.SERVICE_PWD + " not found in request parameter"))
.toString();
String database = connectionProperties
.getOrDefault(Constants.DATABASE_NAME,
new ParamsCannotBeNullOrEmpty(Constants.DATABASE_NAME + " not found in request parameter"))
.toString();
String jdbcurl = "jdbc:redshift://" + host + ":" + port + "/" + database;
LOG.info("Connection url for redshift = '" + jdbcurl + "'");
LOG.info("Connecting with '" + userId + "' user id.");
Class.forName(Constants.REDSHIFT_JDBC_CLASSNAME);
connection = DriverManager.getConnection(jdbcurl, userId, service_pwd);
}
/**
* @param componentSchemaProperties
* - Contains request parameter details
* @return {@link TableEntity}
*/
@SuppressWarnings("unchecked")
@Override
public TableEntity fillComponentSchema(Map componentSchemaProperties)
throws SQLException, ParamsCannotBeNullOrEmpty {
if (componentSchemaProperties.get(Constants.TABLENAME) != null)
tableName = componentSchemaProperties.get(Constants.TABLENAME).toString().trim();
else
query = componentSchemaProperties.get(Constants.QUERY).toString().trim();
LOG.info("Generating schema for redshift using "
+ ((tableName != null) ? "table : " + tableName : "query : " + query));
ResultSet res = null;
TableEntity tableEntity = new TableEntity();
List<TableSchemaFieldEntity> tableSchemaFieldEntities = new ArrayList<TableSchemaFieldEntity>();
try {
Statement stmt = connection.createStatement();
if (query != null && !query.isEmpty())
res = stmt.executeQuery("Select * from (" + query + ") WHERE 1<0");
else if (tableName != null && !tableName.isEmpty())
res = stmt.executeQuery("Select * from " + tableName + " where 1<0");
else {
LOG.error("Table or query cannot be null in requested parameters");
throw new ParamsCannotBeNullOrEmpty("Table or query cannot be null in requested parameters");
}
ResultSetMetaData rsmd = res.getMetaData();
for (int count = 1; count <= rsmd.getColumnCount(); count++) {
TableSchemaFieldEntity tableSchemaFieldEntity = new TableSchemaFieldEntity();
tableSchemaFieldEntity.setFieldName(rsmd.getColumnLabel(count));
if (rsmd.getColumnTypeName(count).equalsIgnoreCase("TIMESTAMP")) {
tableSchemaFieldEntity.setFormat("yyyy-MM-dd HH:mm:ss");
tableSchemaFieldEntity.setFieldType("java.util.Date");
} else if (rsmd.getColumnTypeName(count).equalsIgnoreCase("DATE")) {
tableSchemaFieldEntity.setFormat("yyyy-MM-dd");
tableSchemaFieldEntity.setFieldType("java.util.Date");
} else if (rsmd.getColumnTypeName(count).equalsIgnoreCase("NUMERIC")) {
tableSchemaFieldEntity.setFieldType("java.math.BigDecimal");
tableSchemaFieldEntity.setScaleType("explicit");
tableSchemaFieldEntity.setPrecision(String.valueOf(rsmd.getPrecision(count)));
tableSchemaFieldEntity.setScale(String.valueOf(rsmd.getScale(count)));
} else {
tableSchemaFieldEntity.setFieldType(rsmd.getColumnClassName(count));
}
tableSchemaFieldEntities.add(tableSchemaFieldEntity);
}
if (componentSchemaProperties.get(Constants.TABLENAME) == null)
tableEntity.setQuery(componentSchemaProperties.get(Constants.QUERY).toString());
else
tableEntity.setTableName(componentSchemaProperties.get(Constants.TABLENAME).toString());
tableEntity.setDatabaseName(componentSchemaProperties.get(Constants.dbType).toString());
tableEntity.setSchemaFields(tableSchemaFieldEntities);
res.close();
} finally {
connection.close();
}
return tableEntity;
}
}