org.apache.falcon.regression.core.util.HiveUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.falcon.regression.core.util.HiveUtil.java

Source

/**
 * 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<>();
    }
}