diff --git a/beeline/src/java/org/apache/hive/beeline/BeeLineOpts.java b/beeline/src/java/org/apache/hive/beeline/BeeLineOpts.java index 84f2828..bc11865 100644 --- a/beeline/src/java/org/apache/hive/beeline/BeeLineOpts.java +++ b/beeline/src/java/org/apache/hive/beeline/BeeLineOpts.java @@ -72,6 +72,7 @@ public static final String PROPERTY_PREFIX = "beeline."; public static final String PROPERTY_NAME_EXIT = PROPERTY_PREFIX + "system.exit"; + public static final String DEFAULT_NULL_STRING = "NULL"; private final BeeLine beeLine; private boolean autosave = false; @@ -96,6 +97,7 @@ private String isolation = DEFAULT_ISOLATION_LEVEL; private String outputFormat = "table"; private boolean trimScripts = true; + private String nullString = DEFAULT_NULL_STRING; private final File rcFile = new File(saveDir(), "beeline.properties"); private String historyFile = new File(saveDir(), "history").getAbsolutePath(); @@ -443,4 +445,12 @@ public int getMaxHeight() { public File getPropertiesFile() { return rcFile; } + + public String getNullString() { + return nullString; + } + + public void setNullString(String nullString) { + this.nullString = nullString; + } } diff --git a/beeline/src/java/org/apache/hive/beeline/BufferedRows.java b/beeline/src/java/org/apache/hive/beeline/BufferedRows.java index 4384a52..0d8f429 100644 --- a/beeline/src/java/org/apache/hive/beeline/BufferedRows.java +++ b/beeline/src/java/org/apache/hive/beeline/BufferedRows.java @@ -76,6 +76,11 @@ public Object next() { } @Override + public String toString(){ + return list.toString(); + } + + @Override void normalizeWidths() { int[] max = null; for (Row row : list) { diff --git a/beeline/src/java/org/apache/hive/beeline/Rows.java b/beeline/src/java/org/apache/hive/beeline/Rows.java index aacbf05..df127ad 100644 --- a/beeline/src/java/org/apache/hive/beeline/Rows.java +++ b/beeline/src/java/org/apache/hive/beeline/Rows.java @@ -49,19 +49,23 @@ import java.sql.SQLException; import java.text.DecimalFormat; import java.text.NumberFormat; +import java.util.Arrays; import java.util.Iterator; /** * Abstract base class representing a set of rows to be displayed. + * Holds column values as strings */ abstract class Rows implements Iterator { private final BeeLine beeLine; final ResultSetMetaData rsMeta; final Boolean[] primaryKeys; final NumberFormat numberFormat; + private final String nullStr; Rows(BeeLine beeLine, ResultSet rs) throws SQLException { this.beeLine = beeLine; + this.nullStr = beeLine.getOpts().getNullString(); rsMeta = rs.getMetaData(); int count = rsMeta.getColumnCount(); primaryKeys = new Boolean[count]; @@ -147,6 +151,10 @@ boolean isPrimaryKey(int col) { inserted = false; } + @Override + public String toString(){ + return Arrays.asList(values).toString(); + } Row(int size, ResultSet rs) throws SQLException { isMeta = false; @@ -170,16 +178,17 @@ boolean isPrimaryKey(int col) { if (numberFormat != null) { Object o = rs.getObject(i + 1); if (o == null) { - values[i] = null; + values[i] = nullStr; } else if (o instanceof Number) { values[i] = numberFormat.format(o); } else { values[i] = o.toString(); } } else { - values[i] = rs.getString(i + 1); + String strVal = rs.getString(i + 1); + values[i] = strVal == null ? nullStr : strVal; } - sizes[i] = values[i] == null ? 1 : values[i].length(); + sizes[i] = values[i] == null ? nullStr.length() : values[i].length(); } } } diff --git a/beeline/src/test/org/apache/hive/beeline/src/test/TestBeeLineWithArgs.java b/beeline/src/test/org/apache/hive/beeline/src/test/TestBeeLineWithArgs.java index 2a3848e..d78f0db 100644 --- a/beeline/src/test/org/apache/hive/beeline/src/test/TestBeeLineWithArgs.java +++ b/beeline/src/test/org/apache/hive/beeline/src/test/TestBeeLineWithArgs.java @@ -18,23 +18,27 @@ package org.apache.hive.beeline.src.test; -import java.io.File; -import java.io.IOException; -import java.io.PrintStream; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.FileOutputStream; +import java.io.PrintStream; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; -import junit.framework.TestCase; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.Assert; - +import org.apache.hadoop.fs.Path; import org.apache.hadoop.hive.conf.HiveConf; -import org.apache.hadoop.hive.ql.parse.SemanticException; import org.apache.hive.beeline.BeeLine; +import org.apache.hive.jdbc.TestJdbcDriver2; import org.apache.hive.service.server.HiveServer2; -import org.apache.hive.service.cli.HiveSQLException; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; /** * TestBeeLineWithArgs - executes tests of the command-line arguments to BeeLine @@ -45,7 +49,8 @@ // Default location of HiveServer2 final static String JDBC_URL = BeeLine.BEELINE_DEFAULT_JDBC_URL + "localhost:10000"; - + private static final String tableName = "TestBeelineTable1"; + private static final String tableComment = "Test table comment"; private static HiveServer2 hiveServer2; /** @@ -62,6 +67,45 @@ public static void preTests() throws Exception { System.err.println("Starting HiveServer2..."); hiveServer2.start(); Thread.sleep(1000); + createTable(); + + } + + /** + * 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(JDBC_URL,"", ""); + + 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"); + + HiveConf conf = new HiveConf(TestJdbcDriver2.class); + String dataFileDir = conf.get("test.data.files").replace('\\', '/') + .replace("c:", ""); + Path dataFilePath = new Path(dataFileDir, "kv1.txt"); + // drop table. ignore error. + try { + stmt.execute("drop table " + tableName); + } catch (Exception ex) { + fail(ex.toString()); + } + + // create table + stmt.execute("create table " + tableName + + " (under_col int comment 'the under column', value string) comment '" + + tableComment + "'"); + + // load data + stmt.execute("load data local inpath '" + + dataFilePath.toString() + "' into table " + tableName); } /** @@ -130,7 +174,7 @@ private void testScriptFile(String testName, String scriptText, String expectedP } else { System.err.println("Output: " + output); System.err.println(">>> FAILED " + testName + " (ERROR) " + time); - Assert.fail(testName); + fail(testName); } } catch (Throwable e) { e.printStackTrace(); @@ -144,7 +188,7 @@ private void testScriptFile(String testName, String scriptText, String expectedP if (output.contains(expectedPattern)) { System.err.println("Output: " + output); System.err.println(">>> FAILED " + testName + " (ERROR) " + time); - Assert.fail(testName); + fail(testName); } else { System.out.println(">>> PASSED " + testName + " " + time); } @@ -184,6 +228,33 @@ public void testBreakOnErrorScriptFile() throws Throwable { testScriptFile(TEST_NAME, SCRIPT_TEXT, EXPECTED_PATTERN, false); } + + /** + * Select null from table , check how null is printed + * Print PASSED or FAILED + */ + @Test + public void testNullDefault() throws Throwable { + final String TEST_NAME = "testNullDefault"; + final String SCRIPT_TEXT = "set hive.support.concurrency = false;\n" + + "select null from " + tableName + " limit 1 ;\n"; + final String EXPECTED_PATTERN = "NULL"; + testScriptFile(TEST_NAME, SCRIPT_TEXT, EXPECTED_PATTERN, true); + } + + /** + * Select null from table , check if default null is printed differently + * Print PASSED or FAILED + */ + @Test + public void testNullNonDefault() throws Throwable { + final String TEST_NAME = "testNullNonDefault"; + final String SCRIPT_TEXT = "set hive.support.concurrency = false;\n" + + "!set nullstring nolls;\n select null from " + tableName + " limit 1 ;\n"; + final String EXPECTED_PATTERN = "nolls"; + testScriptFile(TEST_NAME, SCRIPT_TEXT, EXPECTED_PATTERN, true); + } + /** * Attempt to execute a missing script file with the -f option to BeeLine * Print PASSED or FAILED @@ -207,7 +278,7 @@ public void testNegativeScriptFile() throws Throwable { if (output.contains(EXPECTED_PATTERN)) { System.err.println("Output: " + output); System.err.println(">>> FAILED " + TEST_NAME + " (ERROR) " + time); - Assert.fail(TEST_NAME); + fail(TEST_NAME); } else { System.out.println(">>> PASSED " + TEST_NAME + " " + time); }