/** * 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.falcon.regression.core.util; import org.apache.commons.lang.StringUtils; import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.security.UserGroupInformation; import org.apache.log4j.Logger; import java.io.IOException; import java.security.PrivilegedExceptionAction; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Utility class for stuff related to hive. All the methods in this class assume that they are * dealing with small dataset. */ public final class HiveUtil { private HiveUtil() { throw new AssertionError("Instantiating utility class..."); } private static final String DRIVER_NAME = "org.apache.hive.jdbc.HiveDriver"; private static final Logger LOGGER = Logger.getLogger(HiveUtil.class); public static Connection getHiveJdbcConnection(final String jdbcUrl, final String user, final String password, final String hivePrincipal) throws ClassNotFoundException, SQLException, IOException, InterruptedException { final String transportMode = new HiveConf().get("hive.server2.transport.mode", "binary"); String connectionStringSuffix = ""; if (transportMode.equalsIgnoreCase("http")) { connectionStringSuffix += "transportMode=http;httpPath=cliservice;"; } if (MerlinConstants.IS_SECURE) { connectionStringSuffix += String.format("principal=%s;kerberosAuthType=fromSubject;", hivePrincipal); } final String connectionStringSuffix2 = connectionStringSuffix; final UserGroupInformation ugi = KerberosHelper.getUGI(user); final Connection conn = ugi.doAs(new PrivilegedExceptionAction<Connection>() { @Override public Connection run() throws Exception { Class.forName(DRIVER_NAME); return DriverManager.getConnection(jdbcUrl + "/;" + connectionStringSuffix2, ugi.getShortUserName(), password); } }); return conn; } /** * Fetch rows from a given ResultSet and convert is a a list of string, each string is comma * separated column values. The output also has header with column names and footer with * number of rows returned. * @param rs result set * @return List of string - each string corresponds to the output output that you will get on * sql prompt * @throws SQLException */ public static List<String> fetchRows(ResultSet rs) throws SQLException { ResultSetMetaData metaData = rs.getMetaData(); List<String> output = new ArrayList<String>(); int numberOfColumns = metaData.getColumnCount(); StringBuilder sbCol = new StringBuilder(); for (int i = 1; i <= numberOfColumns; i++) { if (i > 1) { sbCol.append(","); } String columnName = metaData.getColumnName(i); // the column name looks like tab1.col1 // we want to remove table name else table equality will fail if (columnName.contains(".")) { columnName = columnName.split("\\.")[1]; } sbCol.append("'").append(columnName).append("'"); } LOGGER.info(sbCol.toString()); output.add(sbCol.toString()); int numberOfRows = 0; while (rs.next()) { StringBuilder sbVal = new StringBuilder(); numberOfRows++; for (int i = 1; i <= numberOfColumns; i++) { if (i > 1) { sbVal.append(","); } String columnValue = rs.getString(i); sbVal.append("'").append(columnValue != null ? columnValue : "").append("'"); } LOGGER.info(sbVal.toString()); output.add(sbVal.toString()); } Collections.sort(output); //sorting to ensure stability results across different runs String rowStr = (numberOfRows > 0 ? numberOfRows : "No") + (numberOfRows == 1 ? " row" : " rows") + " selected"; LOGGER.info(rowStr); output.add(rowStr); return output; } /** * Run a sql using given connection. * @param connection The connection to be used for running sql * @param sql the sql to be run * @throws SQLException * @return output of the query as a List of strings */ public static List<String> runSql(Connection connection, String sql) throws SQLException { Statement stmt = null; try { stmt = connection.createStatement(); LOGGER.info("Executing: " + sql); stmt.execute(sql); final ResultSet resultSet = stmt.getResultSet(); if (resultSet != null) { final List<String> output = fetchRows(resultSet); LOGGER.info("Results are:\n" + StringUtils.join(output, "\n")); return output; } LOGGER.info("Query executed."); } finally { if (stmt != null) { stmt.close(); } } return new ArrayList<>(); } }