diff --git beeline/pom.xml beeline/pom.xml index 6ec1d1a..f16ca32 100644 --- beeline/pom.xml +++ beeline/pom.xml @@ -81,6 +81,11 @@ libthrift ${libthrift.version} + + net.sf.supercsv + super-csv + ${super-csv.version} + org.apache.hive diff --git beeline/src/java/org/apache/hive/beeline/BeeLine.java beeline/src/java/org/apache/hive/beeline/BeeLine.java index 528a98e..68f57a8 100644 --- beeline/src/java/org/apache/hive/beeline/BeeLine.java +++ beeline/src/java/org/apache/hive/beeline/BeeLine.java @@ -79,13 +79,13 @@ import jline.FileNameCompletor; import jline.History; import jline.SimpleCompletor; -import org.apache.hadoop.io.IOUtils; 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; +import org.apache.hadoop.io.IOUtils; /** @@ -146,8 +146,9 @@ private final Map formats = map(new Object[] { "vertical", new VerticalOutputFormat(this), "table", new TableOutputFormat(this), - "csv", new SeparatedValuesOutputFormat(this, ','), - "tsv", new SeparatedValuesOutputFormat(this, '\t'), + "csv", new SeparatedValuesOutputFormat(this, ',',false), + "tsv", new SeparatedValuesOutputFormat(this, '\t',false), + "quotedCsv",new SeparatedValuesOutputFormat(this, ',', true), "xmlattr", new XMLAttributeOutputFormat(this), "xmlelements", new XMLElementOutputFormat(this), }); diff --git beeline/src/java/org/apache/hive/beeline/SeparatedValuesOutputFormat.java beeline/src/java/org/apache/hive/beeline/SeparatedValuesOutputFormat.java index 7853c3f..1253039 100644 --- beeline/src/java/org/apache/hive/beeline/SeparatedValuesOutputFormat.java +++ beeline/src/java/org/apache/hive/beeline/SeparatedValuesOutputFormat.java @@ -22,6 +22,12 @@ */ package org.apache.hive.beeline; +import java.io.IOException; +import java.io.StringWriter; + +import org.apache.hadoop.io.IOUtils; +import org.supercsv.io.CsvListWriter; +import org.supercsv.prefs.CsvPreference; /** * OutputFormat for values separated by a delimiter. * @@ -34,10 +40,19 @@ */ private final BeeLine beeLine; private char separator; + private CsvPreference csvPreference; + private boolean singleQuoted = false; - public SeparatedValuesOutputFormat(BeeLine beeLine, char separator) { + public SeparatedValuesOutputFormat(BeeLine beeLine, char separator, + boolean singleQuoted) { this.beeLine = beeLine; setSeparator(separator); + if (!singleQuoted) { + csvPreference = + new CsvPreference.Builder('"', this.getSeparator(), "") + .surroundingSpacesNeedQuotes(true).build(); + } + this.singleQuoted = singleQuoted; } public int print(Rows rows) { @@ -49,16 +64,44 @@ public int print(Rows rows) { return count - 1; // sans header row } - public void printRow(Rows rows, Rows.Row row) { - String[] vals = row.values; + private String getStrInRFCFormat(String[] vals) { + StringWriter strWriter = new StringWriter(); + CsvListWriter write = new CsvListWriter(strWriter, csvPreference); + if (vals.length > 0) { + try { + write.write(vals); + } catch (IOException e) { + beeLine.error(e); + } finally { + IOUtils.closeStream(write); + } + } + return strWriter.toString(); + } + + private String getStrWithSingleQuoted(String[] vals) { StringBuilder buf = new StringBuilder(); for (int i = 0; i < vals.length; i++) { - buf.append(buf.length() == 0 ? "" : "" + getSeparator()) - .append('\'') - .append(vals[i] == null ? "" : vals[i]) - .append('\''); + buf.append(buf.length() == 0 ? "" : "" + getSeparator()) + .append('\'') + .append(vals[i] == null ? "" : vals[i]) + .append('\''); + } + return buf.toString(); + } + + private String getFormatStr(String[] vals) { + if (this.isSingleQuoted()) { + return getStrWithSingleQuoted(vals); + }else{ + return getStrInRFCFormat(vals); } - beeLine.output(buf.toString()); + } + + public void printRow(Rows rows, Rows.Row row) { + String[] vals = row.values; + String formattedStr = getFormatStr(vals); + beeLine.output(formattedStr); } public void setSeparator(char separator) { @@ -68,4 +111,21 @@ public void setSeparator(char separator) { public char getSeparator() { return this.separator; } + + public CsvPreference getCsvPreference() { + return this.csvPreference; + } + + public void setCsvPreference(CsvPreference csvPreference) { + this.csvPreference = csvPreference; + } + + public boolean isSingleQuoted() { + return singleQuoted; + } + + public void getSingleQuoted(boolean singleQuoted) { + this.singleQuoted = singleQuoted; + } + } diff --git beeline/src/main/resources/BeeLine.properties beeline/src/main/resources/BeeLine.properties index 390d062..069e703 100644 --- beeline/src/main/resources/BeeLine.properties +++ beeline/src/main/resources/BeeLine.properties @@ -68,7 +68,7 @@ help-procedures: List all the procedures help-tables: List all the tables in the database help-columns: List all the columns for the specified table help-properties: Connect to the database specified in the properties file(s) -help-outputformat: Set the output format for displaying results (table,vertical,csv,tsv,xmlattrs,xmlelements) +help-outputformat: Set the output format for displaying results (table,vertical,csv,quotedCsv,tsv,xmlattrs,xmlelements) help-nullemptystring: Set to true to get historic behavior of printing null as empty string. Default is false. jline-missing: The JLine jar was not found. Please ensure it is installed. @@ -166,7 +166,7 @@ cmd-usage: Usage: java org.apache.hive.cli.beeline.BeeLine \n \ \ --maxColumnWidth=MAXCOLWIDTH the maximum width to use when displaying columns\n \ \ --silent=[true/false] be more silent\n \ \ --autosave=[true/false] automatically save preferences\n \ -\ --outputformat=[table/vertical/csv/tsv] format mode for result display\n \ +\ --outputformat=[table/vertical/csv/tsv/quotedCsv] format mode for result display\n \ \ --isolation=LEVEL set the transaction isolation level\n \ \ --nullemptystring=[true/false] set to true to get historic behavior of printing null as empty string\n \ \ --help display this message diff --git itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeeLineWithArgs.java itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeeLineWithArgs.java index 8888bd9..e3553a1 100644 --- itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeeLineWithArgs.java +++ itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeeLineWithArgs.java @@ -365,7 +365,7 @@ public void testNullEmpty() throws Throwable { final String EXPECTED_PATTERN = "'abc','','def'"; List argList = getBaseArgs(JDBC_URL); - argList.add("--outputformat=csv"); + argList.add("--outputformat=quotedCsv"); testScriptFile(TEST_NAME, SCRIPT_TEXT, EXPECTED_PATTERN, true, argList); } @@ -386,7 +386,7 @@ public void testNullEmptyCmdArg() throws Throwable { List argList = getBaseArgs(JDBC_URL); argList.add("--nullemptystring=true"); - argList.add("--outputformat=csv"); + argList.add("--outputformat=quotedCsv"); testScriptFile(TEST_NAME, SCRIPT_TEXT, EXPECTED_PATTERN, true, argList); } diff --git pom.xml pom.xml index b5a5697..57c1c12 100644 --- pom.xml +++ pom.xml @@ -144,6 +144,7 @@ 1.0.1 1.7.5 4.0.4 + 2.2.0 0.4.0-incubating 1.1 0.2