commit 0f0909aabc1154ae0ef23c16e60f5df26b6540d4 Author: Vihang Karajgaonkar Date: Mon Oct 3 15:03:25 2016 -0700 HIVE-13589 : beeline - support prompt for password with '-u' option This change makes the -p option for beeline an option which has a optionalArgument. This means that user can optionally provide a connection url which has -p followed by no password and beeline will prompt for the password on the console when it attempts the connection. There are no changes to previous ways of making the connection. This way of connecting gives user the ability to connect without logging the password in the command history or showing up the password on the screen while connecting. diff --git a/beeline/src/java/org/apache/hive/beeline/BeeLine.java b/beeline/src/java/org/apache/hive/beeline/BeeLine.java index 79922d267eaf13216e8a8e4826c050d334266579..ca3188c7ef5853d6fd58de4333e843c923db240d 100644 --- a/beeline/src/java/org/apache/hive/beeline/BeeLine.java +++ b/beeline/src/java/org/apache/hive/beeline/BeeLine.java @@ -84,9 +84,11 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.GnuParser; +import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; +import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.hive.conf.HiveConf; @@ -321,6 +323,7 @@ .hasArg() .withArgName("password") .withDescription("the password to connect as") + .hasOptionalArg() .create('p')); // -w (or) --password-file @@ -633,23 +636,45 @@ ColorBuffer getColorBuffer(String msg) { public class BeelineParser extends GnuParser { + private boolean isPasswordOptionSet = false; @Override - protected void processOption(final String arg, final ListIterator iter) throws ParseException { - if ((arg.startsWith("--")) && !(arg.equals(HIVE_VAR_PREFIX) || (arg.equals(HIVE_CONF_PREFIX)) - || (arg.equals("--help") || (arg.equals(PROP_FILE_PREFIX))))) { - String stripped = arg.substring(2, arg.length()); - String[] parts = split(stripped, "="); - debug(loc("setting-prop", Arrays.asList(parts))); - if (parts.length >= 2) { - getOpts().set(parts[0], parts[1], true); - } else { - getOpts().set(parts[0], "true", true); - } + protected void processOption(String arg, final ListIterator iter) throws ParseException { + if (isBeeLineOpt(arg)) { + processBeeLineOpt(arg); } else { + //-p with the next argument being for BeeLineOpts + if ("-p".equals(arg)) { + isPasswordOptionSet = true; + if(iter.hasNext()) { + String next = (String) iter.next(); + if(isBeeLineOpt(next)) { + processBeeLineOpt(next); + return; + } else { + iter.previous(); + } + } + } super.processOption(arg, iter); } } + + private void processBeeLineOpt(final String arg) { + String stripped = arg.substring(2, arg.length()); + String[] parts = split(stripped, "="); + debug(loc("setting-prop", Arrays.asList(parts))); + if (parts.length >= 2) { + getOpts().set(parts[0], parts[1], true); + } else { + getOpts().set(parts[0], "true", true); + } + } + + private boolean isBeeLineOpt(String arg) { + return arg.startsWith("--") && !(arg.equals(HIVE_VAR_PREFIX) || (arg.equals(HIVE_CONF_PREFIX)) + || (arg.equals("--help") || (arg.equals(PROP_FILE_PREFIX)))); + } } int initArgsFromCliVars(String[] args) { @@ -728,7 +753,7 @@ int initArgs(String[] args) { return -1; } - String driver = null, user = null, pass = null, url = null; + String driver = null, user = null, pass = "", url = null; String auth = null; @@ -755,7 +780,9 @@ int initArgs(String[] args) { if (cl.hasOption("w")) { pass = obtainPasswordFromFile(cl.getOptionValue("w")); } else { - pass = cl.getOptionValue("p"); + if (beelineParser.isPasswordOptionSet) { + pass = cl.getOptionValue("p"); + } } url = cl.getOptionValue("u"); if ((url == null) && cl.hasOption("reconnect")){ @@ -784,14 +811,6 @@ int initArgs(String[] args) { */ if (url != null) { - if (user == null) { - user = Utils.parsePropertyFromUrl(url, JdbcConnectionParams.AUTH_USER); - } - - if (pass == null) { - pass = Utils.parsePropertyFromUrl(url, JdbcConnectionParams.AUTH_PASSWD); - } - String com = constructCmd(url, user, pass, driver, false); String comForDebug = constructCmd(url, user, pass, driver, true); debug("issuing: " + comForDebug); @@ -834,17 +853,61 @@ private void setHiveConfVar(String key, String val) { } } - private String constructCmd(String url, String user, String pass, String driver, boolean stripPasswd) { - String com = "!connect " - + url + " " - + (user == null || user.length() == 0 ? "''" : user) + " "; - if (stripPasswd) { - com += PASSWD_MASK + " "; - } else { - com += (pass == null || pass.length() == 0 ? "''" : pass) + " "; - } - com += (driver == null ? "" : driver); - return com; + /** + * This is an internal method is used to create !connect command from the information provided. + * Connect command returned should be ; separated key-value pairs along with the url + * We cannot use space separated !connect url user [password] [driver] here since + * both password and driver are now optional and there would be no way to distinguish + * if the fourth string is password or driver + * + * @param url connection url passed using -u argument on the command line + * @param user username passed through command line + * @param pass password passed through the command line using -p argument. Note that + * password can be null when -p is used without an argument. If pass is null, !connect + * command which is returned should not contain password. + * @param driver driver passed through command line -d option + * @param stripPasswd When set to true, generates a !connect command which strips the + * password for logging purposes + * @return !connect command + */ + private String constructCmd(String url, String user, String pass, String driver, + boolean stripPasswd) { + StringBuilder command = new StringBuilder("!connect "); + command.append(url); + command.append(';'); + // if the username is not already available in the URL add the one provided + if (Utils.parsePropertyFromUrl(url, JdbcConnectionParams.AUTH_USER) == null) { + command.append(JdbcConnectionParams.AUTH_USER); + command.append('='); + command.append((user == null || user.length() == 0 ? "''" : user)); + } + // if the password is not already available in the URL add the one provided + if (Utils.parsePropertyFromUrl(url, JdbcConnectionParams.AUTH_PASSWD) == null && pass != null) { + command.append(';'); + command.append(JdbcConnectionParams.AUTH_PASSWD); + command.append("="); + if (stripPasswd) { + command.append(BeeLine.PASSWD_MASK); + } else { + command.append(pass.length() == 0 ? "''" : pass); + } + } else if (stripPasswd) { + // password is available in url which needs to be striped + int startIndex = command.indexOf(JdbcConnectionParams.AUTH_PASSWD + "=") + + JdbcConnectionParams.AUTH_PASSWD.length() + 2; + int endIndex = command.toString().indexOf(";", startIndex); + command.replace(startIndex, (endIndex == -1 ? command.length() : endIndex), + BeeLine.PASSWD_MASK); + } + // if the driver is not already available in the URL add the one provided + if (Utils.parsePropertyFromUrl(url, JdbcConnectionParams.PROPERTY_DRIVER) == null + && driver != null) { + command.append(';'); + command.append(JdbcConnectionParams.PROPERTY_DRIVER); + command.append("="); + command.append(driver); + } + return command.toString(); } /** * Obtains a password from the passed file path. @@ -882,6 +945,9 @@ public int begin(String[] args, InputStream inputStream) throws IOException { } try { + //this method also initializes the consoleReader which is + //needed by initArgs for certain execution paths + ConsoleReader reader = getConsoleReader(inputStream); if (isBeeLine) { int code = initArgs(args); if (code != 0) { @@ -906,7 +972,7 @@ public int begin(String[] args, InputStream inputStream) throws IOException { } catch (Exception e) { // ignore } - ConsoleReader reader = getConsoleReader(inputStream); + return execute(reader, false); } finally { close(); diff --git a/beeline/src/java/org/apache/hive/beeline/Commands.java b/beeline/src/java/org/apache/hive/beeline/Commands.java index 039e3549209682b5ebdde937607b77c3ec094527..3a0e9889ef3eb0c7b7bcf5893162325f07838f1c 100644 --- a/beeline/src/java/org/apache/hive/beeline/Commands.java +++ b/beeline/src/java/org/apache/hive/beeline/Commands.java @@ -1036,11 +1036,12 @@ private boolean executeInternal(String sql, boolean call) { return true; } + /* + * Checks if the input line is a multi-line command which needs to read further + */ public String handleMultiLineCmd(String line) throws IOException { - //When using -e, console reader is not initialized and command is a single line - while (beeLine.getConsoleReader() != null && !(line.trim().endsWith(";")) && beeLine.getOpts() - .isAllowMultiLineCommand()) { - + //When using -e, console reader is not initialized and command is always a single line + while (isMultiLine(line) && beeLine.getOpts().isAllowMultiLineCommand()) { StringBuilder prompt = new StringBuilder(beeLine.getPrompt()); if (!beeLine.getOpts().isSilent()) { for (int i = 0; i < prompt.length() - 1; i++) { @@ -1051,6 +1052,11 @@ public String handleMultiLineCmd(String line) throws IOException { } String extra; + //avoid NPE below if for some reason -e argument has multi-line command + if(beeLine.getConsoleReader() == null) { + beeLine.error("Console reader not initialized"); + break; + } if (beeLine.getOpts().isSilent() && beeLine.getOpts().getScriptFile() != null) { extra = beeLine.getConsoleReader().readLine(null, jline.console.ConsoleReader.NULL_MASK); } else { @@ -1067,6 +1073,26 @@ public String handleMultiLineCmd(String line) throws IOException { return line; } + //returns true if statement represented by line is + //not complete and needs additional reading from + //console. Used in handleMultiLineCmd method + //assumes line would never be null when this method is called + private boolean isMultiLine(String line) { + line = line.trim(); + if (line.endsWith(";")) { + return false; + } + if (beeLine.isComment(line)) { + return false; + } + // handles the case like line = show tables; --test comment + List cmds = getCmdList(line, false); + if(!cmds.isEmpty() && cmds.get(cmds.size()-1).trim().startsWith("--")) { + return false; + } + return true; + } + public boolean sql(String line, boolean entireLineAsCommand) { return execute(line, false, entireLineAsCommand); } @@ -1507,12 +1533,13 @@ public boolean connect(Properties props) throws IOException { beeLine.info("Connecting to " + url); if (Utils.parsePropertyFromUrl(url, JdbcConnectionParams.AUTH_PRINCIPAL) == null) { + String urlForPrompt = url.substring(0, url.contains(";") ? url.indexOf(';') : url.length()); if (username == null) { - username = beeLine.getConsoleReader().readLine("Enter username for " + url + ": "); + username = beeLine.getConsoleReader().readLine("Enter username for " + urlForPrompt + ": "); } props.setProperty(JdbcConnectionParams.AUTH_USER, username); if (password == null) { - password = beeLine.getConsoleReader().readLine("Enter password for " + url + ": ", + password = beeLine.getConsoleReader().readLine("Enter password for " + urlForPrompt + ": ", new Character('*')); } props.setProperty(JdbcConnectionParams.AUTH_PASSWD, password); diff --git a/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java b/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java index a83f925df25be5801f885f4570fb8aaf5ab18c88..21720874056271adb6612ea3a1db7669aabbd04a 100644 --- a/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java +++ b/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java @@ -111,7 +111,7 @@ public void testSimpleArgs() throws Exception { String args[] = new String[] {"-u", "url", "-n", "name", "-p", "password", "-d", "driver", "-a", "authType"}; org.junit.Assert.assertEquals(0, bl.initArgs(args)); - Assert.assertTrue(bl.connectArgs.equals("url name password driver")); + Assert.assertTrue(bl.connectArgs.equals("url;user=name;password=password;driver=driver")); Assert.assertTrue(bl.getOpts().getAuthType().equals("authType")); } @@ -129,7 +129,7 @@ public void testPasswordFileArgs() throws Exception { bl.initArgs(args); System.out.println(bl.connectArgs); // Password file contents are trimmed of trailing whitespaces and newlines - Assert.assertTrue(bl.connectArgs.equals("url name mypass driver")); + Assert.assertTrue(bl.connectArgs.equals("url;user=name;password=mypass;driver=driver")); Assert.assertTrue(bl.getOpts().getAuthType().equals("authType")); passFile.delete(); } @@ -143,7 +143,7 @@ public void testDuplicateArgs() throws Exception { String args[] = new String[] {"-u", "url", "-u", "url2", "-n", "name", "-p", "password", "-d", "driver"}; Assert.assertEquals(0, bl.initArgs(args)); - Assert.assertTrue(bl.connectArgs.equals("url name password driver")); + Assert.assertTrue(bl.connectArgs.equals("url;user=name;password=password;driver=driver")); } @Test @@ -152,7 +152,7 @@ public void testQueryScripts() throws Exception { String args[] = new String[] {"-u", "url", "-n", "name", "-p", "password", "-d", "driver", "-e", "select1", "-e", "select2"}; Assert.assertEquals(0, bl.initArgs(args)); - Assert.assertTrue(bl.connectArgs.equals("url name password driver")); + Assert.assertTrue(bl.connectArgs.equals("url;user=name;password=password;driver=driver")); Assert.assertTrue(bl.queries.contains("select1")); Assert.assertTrue(bl.queries.contains("select2")); } @@ -167,7 +167,7 @@ public void testHiveConfAndVars() throws Exception { "-p", "password", "-d", "driver", "--hiveconf", "a=avalue", "--hiveconf", "b=bvalue", "--hivevar", "c=cvalue", "--hivevar", "d=dvalue"}; Assert.assertEquals(0, bl.initArgs(args)); - Assert.assertTrue(bl.connectArgs.equals("url name password driver")); + Assert.assertTrue(bl.connectArgs.equals("url;user=name;password=password;driver=driver")); Assert.assertTrue(bl.getOpts().getHiveConfVariables().get("a").equals("avalue")); Assert.assertTrue(bl.getOpts().getHiveConfVariables().get("b").equals("bvalue")); Assert.assertTrue(bl.getOpts().getHiveVariables().get("c").equals("cvalue")); @@ -181,7 +181,7 @@ public void testBeelineOpts() throws Exception { new String[] { "-u", "url", "-n", "name", "-p", "password", "-d", "driver", "--autoCommit=true", "--verbose", "--truncateTable" }; Assert.assertEquals(0, bl.initArgs(args)); - Assert.assertTrue(bl.connectArgs.equals("url name password driver")); + Assert.assertTrue(bl.connectArgs.equals("url;user=name;password=password;driver=driver")); Assert.assertTrue(bl.getOpts().getAutoCommit()); Assert.assertTrue(bl.getOpts().getVerbose()); Assert.assertTrue(bl.getOpts().getTruncateTable()); @@ -215,7 +215,7 @@ public void testScriptFile() throws Exception { String args[] = new String[] {"-u", "url", "-n", "name", "-p", "password", "-d", "driver", "-f", "myscript"}; Assert.assertEquals(0, bl.initArgs(args)); - Assert.assertTrue(bl.connectArgs.equals("url name password driver")); + Assert.assertTrue(bl.connectArgs.equals("url;user=name;password=password;driver=driver")); Assert.assertTrue(bl.getOpts().getScriptFile().equals("myscript")); } diff --git a/beeline/src/test/resources/hive-site.xml b/beeline/src/test/resources/hive-site.xml index 5f310d68245275ac9dc24df45579784019eea332..fdda94bba292123cfdb1cf75b09cfca2408283b9 100644 --- a/beeline/src/test/resources/hive-site.xml +++ b/beeline/src/test/resources/hive-site.xml @@ -45,4 +45,9 @@ ${test.tmp.dir}/warehouse + + test.data.files + ${hive.root}/data/files + + diff --git a/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeelinePasswordOption.java b/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeelinePasswordOption.java new file mode 100644 index 0000000000000000000000000000000000000000..b3e5cff4f7ebbac7855a693c2872acebf14236f7 --- /dev/null +++ b/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeelinePasswordOption.java @@ -0,0 +1,326 @@ +/** + * 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.hive.beeline; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hive.jdbc.miniHS2.MiniHS2; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TestBeelinePasswordOption { + private static final String tableName = "TestBeelineTable1"; + private static final String tableComment = "Test table comment"; + private static MiniHS2 miniHS2; + private static final Logger LOG = LoggerFactory.getLogger(TestBeelinePasswordOption.class); + + /** + * Start up a local Hive Server 2 for these tests + */ + @BeforeClass + public static void preTests() throws Exception { + HiveConf hiveConf = new HiveConf(); + // Set to non-zk lock manager to prevent HS2 from trying to connect + hiveConf.setVar(HiveConf.ConfVars.HIVE_LOCK_MANAGER, + "org.apache.hadoop.hive.ql.lockmgr.EmbeddedLockManager"); + hiveConf.setBoolVar(HiveConf.ConfVars.HIVEOPTIMIZEMETADATAQUERIES, false); + miniHS2 = new MiniHS2(hiveConf); + miniHS2.start(new HashMap()); + createTable(); + } + + /** + * Test if beeline prompts for a password when optional password option is at the beginning of + * arguments + */ + @Test + public void testPromptPasswordOptionStart() throws Throwable { + List argList = new ArrayList<>(); + argList.add("-p"); + argList.addAll(getBaseArgs(miniHS2.getBaseJdbcURL())); + argList.add("-n"); + argList.add("hive"); + connectBeelineWithUserPrompt(argList, "hivepassword"); + } + + /** + * Test if beeline prompts for a password when optional password option is at the end of arguments + */ + @Test + public void testPromptPasswordOptionLast() throws Exception { + List argList = getBaseArgs(miniHS2.getBaseJdbcURL()); + argList.add("-n"); + argList.add("hive"); + argList.add("-p"); + connectBeelineWithUserPrompt(argList, "hivepassword"); + } + + /** + * Test if beeline prompts for a password when optional password option is at the middle of + * arguments + */ + @Test + public void testPromptPasswordOptionMiddle() throws Exception { + List argList = getBaseArgs(miniHS2.getBaseJdbcURL()); + argList.add("-p"); + argList.add("-n"); + argList.add("hive"); + connectBeelineWithUserPrompt(argList, "hivepassword"); + } + + /** + * Test if beeline prompts for a password when optional password option is used in conjunction + * with additional commandLine options after -p + */ + @Test + public void testPromptPasswordOptionWithOtherOptions() throws Exception { + List argList = getBaseArgs(miniHS2.getBaseJdbcURL()); + argList.add("-p"); + argList.add("-n"); + argList.add("hive"); + argList.add("-e"); + argList.add("show tables;"); + String output = connectBeelineWithUserPrompt(argList, "hivepassword"); + Assert.assertTrue("Table name " + tableName + " not found in the output", + output.contains(tableName.toLowerCase())); + } + + /** + * Test if beeline prompts for a password when optional password option is used in conjunction + * with additional BeeLineOpts options after -p + */ + @Test + public void testPromptPasswordOptionWithBeelineOpts() throws Exception { + List argList = getBaseArgs(miniHS2.getBaseJdbcURL()); + argList.add("-n"); + argList.add("hive"); + argList.add("-p"); + argList.add("--force=true"); + argList.add("-e"); + argList.add("show tables;"); + String output = connectBeelineWithUserPrompt(argList, "hivepassword"); + Assert.assertTrue("Table name " + tableName + " not found in the output", + output.contains(tableName.toLowerCase())); + } + + /** + * Test if beeline prompts for a password when optional password option is used in conjunction + * with additional BeeLineOpts options after -p. Also, verifies the beelineOpt value is set as + * expected + */ + @Test + public void testPromptPasswordVerifyBeelineOpts() throws Exception { + List argList = getBaseArgs(miniHS2.getBaseJdbcURL()); + argList.add("-n"); + argList.add("hive"); + argList.add("-p"); + argList.add("--maxColumnWidth=57"); + argList.add("-e"); + argList.add("show tables;"); + String output = connectWithPromptAndVerify(argList, "hivepassword", true, 57, null, null); + Assert.assertTrue("Table name " + tableName + " not found in the output", + output.contains(tableName.toLowerCase())); + } + + /** + * Tests if beeline prompts for a password and also confirms that --hiveconf + * argument works when given immediately after -p with no password + * @throws Exception + */ + @Test + public void testPromptPasswordWithHiveConf() throws Exception { + List argList = getBaseArgs(miniHS2.getBaseJdbcURL()); + argList.add("-n"); + argList.add("hive"); + argList.add("-p"); + argList.add("--hiveconf"); + argList.add("hive.cli.print.header=true"); + argList.add("-e"); + argList.add("show tables;"); + String output = connectWithPromptAndVerify(argList, "hivepassword", false, null, + "hive.cli.print.header", "true"); + Assert.assertTrue("Table name " + tableName + " not found in the output", + output.contains(tableName.toLowerCase())); + } + + /** + * Tests if beeline doesn't prompt for a password and connects with empty password + * when no password option provided + */ + @Test + public void testNoPasswordPrompt() throws Exception { + List argList = getBaseArgs(miniHS2.getBaseJdbcURL()); + argList.add("-n"); + argList.add("hive"); + argList.add("--force=true"); + argList.add("-e"); + argList.add("show tables;"); + String output = connectBeelineWithUserPrompt(argList); + Assert.assertTrue("Table name " + tableName + " not found in the output", + output.contains(tableName.toLowerCase())); + } + + /** + * Tests if beeline doesn't prompt for a password and connects with no password/username option + * provided + */ + @Test + public void testNoPasswordPrompt2() throws Exception { + List argList = getBaseArgs(miniHS2.getBaseJdbcURL()); + argList.add("--force=true"); + argList.add("-e"); + argList.add("show tables;"); + String output = connectBeelineWithUserPrompt(argList); + Assert.assertTrue("Table name " + tableName + " not found in the output", + output.contains(tableName.toLowerCase())); + } + + /** + * Tests if Beeline prompts for password when -p is the last argument and argList has CommandLine + * options as well as BeelineOpts + */ + @Test + public void testPromptPassOptionLastWithBeelineOpts() throws Exception { + List argList = getBaseArgs(miniHS2.getBaseJdbcURL()); + argList.add("-n"); + argList.add("hive"); + argList.add("--force=true"); + argList.add("-e"); + argList.add("show tables;"); + argList.add("-p"); + String output = connectBeelineWithUserPrompt(argList, "hivepassword"); + Assert.assertTrue("Table name " + tableName + " not found in the output", + output.contains(tableName.toLowerCase())); + } + + /** + * Connects to miniHS2 using beeline with the given string value for the prompt if the prompt is + * null, uses beeline with null inputstream in which this method expects that the argList is + * sufficient to make a successful Beeline connection with no prompt required from user + * + * @param argList - arguments list for the beeline + * @param prompt - String value to be given to beeline prompt during connection + * @param beelineOptName - Name of BeelineOpt to be verified + * @param beelineOptValue - Expected value of value of BeeLineOpt + * @param hiveConfKey - hive conf variable name to verify + * @param expectedHiveConfValue - Expected value of hive conf variable + * @return output of beeline from outputstream + * @throws Exception + */ + private String connectWithPromptAndVerify(List argList, String prompt, + boolean testMaxColumnWidthOption, Integer expectedMaxColumnWidth, String hiveConfKey, + String expectedHiveConfValue) throws Exception { + BeeLine beeLine = null; + try { + beeLine = new BeeLine(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + PrintStream beelineOutputStream = new PrintStream(os); + beeLine.setOutputStream(beelineOutputStream); + beeLine.setErrorStream(beelineOutputStream); + String[] args = argList.toArray(new String[argList.size()]); + InputStream inputStream = null; + if (prompt != null) { + inputStream = new ByteArrayInputStream(prompt.getBytes()); + } + Assert.assertTrue(beeLine.begin(args, inputStream) == 0); + if (testMaxColumnWidthOption) { + int maxColumnWidth = beeLine.getOpts().getMaxColumnWidth(); + Assert.assertTrue( + "Expected max columnWidth to be " + expectedMaxColumnWidth + " found " + maxColumnWidth, + maxColumnWidth == expectedMaxColumnWidth); + } + if (hiveConfKey != null) { + String hiveConfValue = beeLine.getOpts().getHiveConfVariables().get(hiveConfKey); + Assert.assertTrue( + "Expected " + expectedHiveConfValue + " got " + hiveConfValue + " for " + hiveConfKey, + expectedHiveConfValue.equalsIgnoreCase(hiveConfValue)); + } + String output = os.toString("UTF-8"); + LOG.debug(output); + return output; + } finally { + if (beeLine != null) { + beeLine.close(); + } + } + } + + private String connectBeelineWithUserPrompt(List argList) throws Exception { + return connectBeelineWithUserPrompt(argList, null); + } + + private String connectBeelineWithUserPrompt(List argList, String prompt) + throws Exception { + return connectWithPromptAndVerify(argList, prompt, false, null, null, null); + } + + /** + * Create table for use by tests + * + * @throws ClassNotFoundException + * @throws SQLException + */ + private static void createTable() throws ClassNotFoundException, SQLException { + Class.forName(BeeLine.BEELINE_DEFAULT_JDBC_DRIVER); + Connection con = DriverManager.getConnection(miniHS2.getBaseJdbcURL(), "", ""); + + assertNotNull("Connection is null", con); + assertFalse("Connection should not be closed", con.isClosed()); + Statement stmt = con.createStatement(); + assertNotNull("Statement is null", stmt); + + stmt.execute("set hive.support.concurrency = false"); + try { + stmt.execute("drop table if exists " + tableName); + } catch (Exception ex) { + LOG.error("Failed due to exception ", ex); + fail("Unable to create setup table " + tableName + ex.toString()); + } + // create table + stmt.execute("create table " + tableName + + " (under_col int comment 'the under column', value string) comment '" + tableComment + + "'"); + } + + private List getBaseArgs(String jdbcUrl) { + List argList = new ArrayList(8); + argList.add("-d"); + argList.add(BeeLine.BEELINE_DEFAULT_JDBC_DRIVER); + argList.add("-u"); + argList.add(jdbcUrl); + return argList; + } +}