You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by xu...@apache.org on 2014/03/30 17:17:56 UTC

svn commit: r1583152 - in /hive/trunk/beeline/src: java/org/apache/hive/beeline/BeeLine.java test/org/apache/hive/beeline/TestBeelineArgParsing.java

Author: xuefu
Date: Sun Mar 30 15:17:55 2014
New Revision: 1583152

URL: http://svn.apache.org/r1583152
Log:
Beeline throws ArrayIndexOutOfBoundsException for mismatched arguments (Szehon via Xuefu)

Added:
    hive/trunk/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java
Modified:
    hive/trunk/beeline/src/java/org/apache/hive/beeline/BeeLine.java

Modified: hive/trunk/beeline/src/java/org/apache/hive/beeline/BeeLine.java
URL: http://svn.apache.org/viewvc/hive/trunk/beeline/src/java/org/apache/hive/beeline/BeeLine.java?rev=1583152&r1=1583151&r2=1583152&view=diff
==============================================================================
--- hive/trunk/beeline/src/java/org/apache/hive/beeline/BeeLine.java (original)
+++ hive/trunk/beeline/src/java/org/apache/hive/beeline/BeeLine.java Sun Mar 30 15:17:55 2014
@@ -58,7 +58,9 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Map;
+import java.util.Properties;
 import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.SortedSet;
@@ -76,6 +78,12 @@ import jline.ConsoleReader;
 import jline.FileNameCompletor;
 import jline.SimpleCompletor;
 
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+
 
 /**
  * A console SQL shell with command completion.
@@ -115,6 +123,8 @@ public class BeeLine {
   private List<String> batch = null;
   private final Reflector reflector;
 
+  private static final Options options = new Options();
+
   public static final String BEELINE_DEFAULT_JDBC_DRIVER = "org.apache.hive.jdbc.HiveDriver";
   public static final String BEELINE_DEFAULT_JDBC_URL = "jdbc:hive2://";
 
@@ -245,6 +255,81 @@ public class BeeLine {
     }
   }
 
+  static {
+    // -d <driver class>
+    options.addOption(OptionBuilder
+        .hasArg()
+        .withArgName("driver class")
+        .withDescription("the driver class to use")
+        .create('d'));
+
+    // -u <database url>
+    options.addOption(OptionBuilder
+        .hasArg()
+        .withArgName("database url")
+        .withDescription("the JDBC URL to connect to")
+        .create('u'));
+
+    // -n <username>
+    options.addOption(OptionBuilder
+        .hasArg()
+        .withArgName("username")
+        .withDescription("the username to connect as")
+        .create('n'));
+
+    // -p <password>
+    options.addOption(OptionBuilder
+        .hasArg()
+        .withArgName("password")
+        .withDescription("the password to connect as")
+        .create('p'));
+
+    // -a <authType>
+    options.addOption(OptionBuilder
+        .hasArg()
+        .withArgName("authType")
+        .withDescription("the authentication type")
+        .create('a'));
+
+    // -e <query>
+    options.addOption(OptionBuilder
+        .hasArgs()
+        .withArgName("query")
+        .withDescription("query that should be executed")
+        .create('e'));
+
+    // -f <file>
+    options.addOption(OptionBuilder
+        .hasArg()
+        .withArgName("file")
+        .withDescription("script file that should be executed")
+        .create('f'));
+
+    // -help
+    options.addOption(OptionBuilder
+        .withLongOpt("help")
+        .withDescription("display this message")
+        .create('h'));
+
+    // Substitution option --hivevar
+    options.addOption(OptionBuilder
+        .withValueSeparator()
+        .hasArgs(2)
+        .withArgName("key=value")
+        .withLongOpt("hivevar")
+        .withDescription("hive variable name and value")
+        .create());
+
+    //hive conf option --hiveconf
+    options.addOption(OptionBuilder
+        .withValueSeparator()
+        .hasArgs(2)
+        .withArgName("property=value")
+        .withLongOpt("hiveconf")
+        .withDescription("Use value for given property")
+        .create());
+  }
+
 
   static Manifest getManifest() throws IOException {
     URL base = BeeLine.class.getResource("/META-INF/MANIFEST.MF");
@@ -498,79 +583,72 @@ public class BeeLine {
   }
 
 
-  boolean initArgs(String[] args) {
-    List<String> commands = new LinkedList<String>();
-    List<String> files = new LinkedList<String>();
-    String driver = null, user = null, pass = null, url = null, cmd = null;
-    String auth = null;
+  public class BeelineParser extends GnuParser {
 
-    for (int i = 0; i < args.length; i++) {
-      if (args[i].equals("--help") || args[i].equals("-h")) {
-        // Return false here, so usage will be printed.
-        return false;
-      }
-
-      // Parse hive variables
-      if (args[i].equals(HIVE_VAR_PREFIX)) {
-        String[] parts = split(args[++i], "=");
-        if (parts.length != 2) {
-          return 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")))) {
+        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);
         }
-        getOpts().getHiveVariables().put(parts[0], parts[1]);
-        continue;
+      } else {
+        super.processOption(arg, iter);
       }
+    }
 
-      // Parse hive conf variables
-      if (args[i].equals(HIVE_CONF_PREFIX)) {
-        String[] parts = split(args[++i], "=");
-        if (parts.length != 2) {
-          return false;
-        }
-        getOpts().getHiveConfVariables().put(parts[0], parts[1]);
-        continue;
-      }
+  }
 
-      // -- arguments are treated as properties
-      if (args[i].startsWith("--")) {
-        String[] parts = split(args[i].substring(2), "=");
-        debug(loc("setting-prop", Arrays.asList(parts)));
-        if (parts.length > 0) {
-          boolean ret;
+  boolean initArgs(String[] args) {
+    List<String> commands = new LinkedList<String>();
+    List<String> files = new LinkedList<String>();
 
-          if (parts.length >= 2) {
-            ret = getOpts().set(parts[0], parts[1], true);
-          } else {
-            ret = getOpts().set(parts[0], "true", true);
-          }
+    CommandLine cl;
+    BeelineParser beelineParser;
 
-          if (!ret) {
-            return false;
-          }
+    try {
+      beelineParser = new BeelineParser();
+      cl = beelineParser.parse(options, args);
+    } catch (ParseException e1) {
+      output(e1.getMessage());
+      return false;
+    }
 
-        }
-        continue;
-      }
+    String driver = null, user = null, pass = null, url = null, cmd = null;
+    String auth = null;
 
-      if (args[i].equals("-d")) {
-        driver = args[i++ + 1];
-      } else if (args[i].equals("-n")) {
-        user = args[i++ + 1];
-      } else if (args[i].equals("-a")) {
-        auth = args[i++ + 1];
-        getOpts().setAuthType(auth);
-      } else if (args[i].equals("-p")) {
-        pass = args[i++ + 1];
-      } else if (args[i].equals("-u")) {
-        url = args[i++ + 1];
-      } else if (args[i].equals("-e")) {
-        commands.add(args[i++ + 1]);
-      } else if (args[i].equals("-f")) {
-        getOpts().setScriptFile(args[i++ + 1]);
-      } else {
-        return error(loc("unrecognized-argument", args[i]));
-      }
+
+    if (cl.hasOption("help")) {
+      // Return false here, so usage will be printed.
+      return false;
     }
 
+    Properties hiveVars = cl.getOptionProperties("hivevar");
+    for (String key : hiveVars.stringPropertyNames()) {
+      getOpts().getHiveVariables().put(key, hiveVars.getProperty(key));
+    }
+
+    Properties hiveConfs = cl.getOptionProperties("hiveconf");
+    for (String key : hiveConfs.stringPropertyNames()) {
+      getOpts().getHiveConfVariables().put(key, hiveConfs.getProperty(key));
+    }
+
+    driver = cl.getOptionValue("d");
+    auth = cl.getOptionValue("a");
+    user = cl.getOptionValue("n");
+    getOpts().setAuthType(auth);
+    pass = cl.getOptionValue("p");
+    url = cl.getOptionValue("u");
+    getOpts().setScriptFile(cl.getOptionValue("f"));
+    if (cl.getOptionValues('e') != null) {
+      commands = Arrays.asList(cl.getOptionValues('e'));
+    }
+
+
     // TODO: temporary disable this for easier debugging
     /*
     if (url == null) {

Added: hive/trunk/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java
URL: http://svn.apache.org/viewvc/hive/trunk/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java?rev=1583152&view=auto
==============================================================================
--- hive/trunk/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java (added)
+++ hive/trunk/beeline/src/test/org/apache/hive/beeline/TestBeelineArgParsing.java Sun Mar 30 15:17:55 2014
@@ -0,0 +1,148 @@
+/**
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+/**
+ * Unit test for Beeline arg parser.
+ */
+public class TestBeelineArgParsing {
+
+  public class TestBeeline extends BeeLine {
+
+    String connectArgs = null;
+    List<String> properties = new ArrayList<String>();
+    List<String> queries = new ArrayList<String>();
+
+    @Override
+    boolean dispatch(String command) {
+      String connectCommand = "!connect";
+      String propertyCommand = "!property";
+      if (command.startsWith(connectCommand)) {
+        this.connectArgs = command.substring(connectCommand.length() + 1, command.length());
+      } else if (command.startsWith(propertyCommand)) {
+        this.properties.add(command.substring(propertyCommand.length() + 1, command.length()));
+      } else {
+        this.queries.add(command);
+      }
+      return true;
+    }
+  }
+
+  @Test
+  public void testSimpleArgs() throws Exception {
+    TestBeeline bl = new TestBeeline();
+    String args[] = new String[] {"-u", "url", "-n", "name",
+      "-p", "password", "-d", "driver", "-a", "authType"};
+    Assert.assertTrue(bl.initArgs(args));
+    Assert.assertTrue(bl.connectArgs.equals("url name password driver"));
+    Assert.assertTrue(bl.getOpts().getAuthType().equals("authType"));
+  }
+
+  /**
+   * The first flag is taken by the parser.
+   */
+  @Test
+  public void testDuplicateArgs() throws Exception {
+    TestBeeline bl = new TestBeeline();
+    String args[] = new String[] {"-u", "url", "-u", "url2", "-n", "name",
+      "-p", "password", "-d", "driver"};
+    Assert.assertTrue(bl.initArgs(args));
+    Assert.assertTrue(bl.connectArgs.equals("url name password driver"));
+  }
+
+  @Test
+  public void testQueryScripts() throws Exception {
+    TestBeeline bl = new TestBeeline();
+    String args[] = new String[] {"-u", "url", "-n", "name",
+      "-p", "password", "-d", "driver", "-e", "select1", "-e", "select2"};
+    Assert.assertTrue(bl.initArgs(args));
+    Assert.assertTrue(bl.connectArgs.equals("url name password driver"));
+    Assert.assertTrue(bl.queries.contains("select1"));
+    Assert.assertTrue(bl.queries.contains("select2"));
+  }
+
+  /**
+   * Test setting hive conf and hive vars with --hiveconf and --hivevar
+   */
+  @Test
+  public void testHiveConfAndVars() throws Exception {
+    TestBeeline bl = new TestBeeline();
+    String args[] = new String[] {"-u", "url", "-n", "name",
+      "-p", "password", "-d", "driver", "--hiveconf", "a=avalue", "--hiveconf", "b=bvalue",
+      "--hivevar", "c=cvalue", "--hivevar", "d=dvalue"};
+    Assert.assertTrue(bl.initArgs(args));
+    Assert.assertTrue(bl.connectArgs.equals("url name password 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"));
+    Assert.assertTrue(bl.getOpts().getHiveVariables().get("d").equals("dvalue"));
+  }
+
+  @Test
+  public void testBeelineOpts() throws Exception {
+    TestBeeline bl = new TestBeeline();
+    String args[] = new String[] {"-u", "url", "-n", "name",
+      "-p", "password", "-d", "driver", "--autoCommit=true", "--verbose"};
+    Assert.assertTrue(bl.initArgs(args));
+    Assert.assertTrue(bl.connectArgs.equals("url name password driver"));
+    Assert.assertTrue(bl.getOpts().getAutoCommit());
+    Assert.assertTrue(bl.getOpts().getVerbose());
+  }
+
+  /**
+   * Test setting script file with -f option.
+   */
+  @Test
+  public void testScriptFile() throws Exception {
+    TestBeeline bl = new TestBeeline();
+    String args[] = new String[] {"-u", "url", "-n", "name",
+      "-p", "password", "-d", "driver", "-f", "myscript"};
+    Assert.assertTrue(bl.initArgs(args));
+    Assert.assertTrue(bl.connectArgs.equals("url name password driver"));
+    Assert.assertTrue(bl.getOpts().getScriptFile().equals("myscript"));
+  }
+
+  /**
+   * Displays the usage.
+   */
+  @Test
+  public void testHelp() throws Exception {
+    TestBeeline bl = new TestBeeline();
+    String args[] = new String[] {"--help"};
+    Assert.assertFalse(bl.initArgs(args));
+  }
+
+  /**
+   * Displays the usage.
+   */
+  @Test
+  public void testUnmatchedArgs() throws Exception {
+    TestBeeline bl = new TestBeeline();
+    String args[] = new String[] {"-u", "url", "-n"};
+    Assert.assertFalse(bl.initArgs(args));
+  }
+
+}