This is an automated email from the ASF dual-hosted git repository. szita pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push: new 5cb1b10e9f6 HIVE-26745: HPL unable to handle Decimal or null values in hplsql mode (#3769) (Adam Szita, reviewed by Attila Magyar and Denys Kuzmenko) 5cb1b10e9f6 is described below commit 5cb1b10e9f696a0b514a5ddb816d60fa61b7aca7 Author: Adam Szita <40628386+sz...@users.noreply.github.com> AuthorDate: Thu Nov 17 11:38:49 2022 +0100 HIVE-26745: HPL unable to handle Decimal or null values in hplsql mode (#3769) (Adam Szita, reviewed by Attila Magyar and Denys Kuzmenko) --- .../src/main/java/org/apache/hive/hplsql/Var.java | 4 +- .../apache/hive/beeline/TestBeeLineWithArgs.java | 4 +- .../apache/hive/beeline/TestHplSqlViaBeeLine.java | 52 +++++++++++++++------- .../cli/operation/hplsql/HplSqlQueryExecutor.java | 11 +++++ 4 files changed, 51 insertions(+), 20 deletions(-) diff --git a/hplsql/src/main/java/org/apache/hive/hplsql/Var.java b/hplsql/src/main/java/org/apache/hive/hplsql/Var.java index bd60b06f7d8..198a4d0b09a 100644 --- a/hplsql/src/main/java/org/apache/hive/hplsql/Var.java +++ b/hplsql/src/main/java/org/apache/hive/hplsql/Var.java @@ -255,11 +255,11 @@ public class Var { cast(new Var(queryResult.column(idx, String.class))); } else if (type == java.sql.Types.INTEGER || type == java.sql.Types.BIGINT || type == java.sql.Types.SMALLINT || type == java.sql.Types.TINYINT) { - cast(new Var(Long.valueOf(queryResult.column(idx, Long.class)))); + cast(new Var(queryResult.column(idx, Long.class))); } else if (type == java.sql.Types.DECIMAL || type == java.sql.Types.NUMERIC) { cast(new Var(queryResult.column(idx, BigDecimal.class))); } else if (type == java.sql.Types.FLOAT || type == java.sql.Types.DOUBLE) { - cast(new Var(Double.valueOf(queryResult.column(idx, Double.class)))); + cast(new Var(queryResult.column(idx, Double.class))); } return this; } diff --git a/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeeLineWithArgs.java b/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeeLineWithArgs.java index 902ab2a2cd7..e8ebf251297 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeeLineWithArgs.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestBeeLineWithArgs.java @@ -63,7 +63,7 @@ import org.junit.Test; * */ public class TestBeeLineWithArgs { - private enum OutStream { + enum OutStream { ERR, OUT } @@ -158,7 +158,7 @@ import org.junit.Test; * @return The stderr and stdout from running the script * @throws Throwable */ - private static String testCommandLineScript(List<String> argList, InputStream inputStream, + static String testCommandLineScript(List<String> argList, InputStream inputStream, OutStream streamType) throws Throwable { BeeLine beeLine = new BeeLine(); diff --git a/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestHplSqlViaBeeLine.java b/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestHplSqlViaBeeLine.java index 269d499a067..f8dcaed6c36 100644 --- a/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestHplSqlViaBeeLine.java +++ b/itests/hive-unit/src/test/java/org/apache/hive/beeline/TestHplSqlViaBeeLine.java @@ -20,12 +20,12 @@ package org.apache.hive.beeline; +import static org.apache.hive.beeline.TestBeeLineWithArgs.OutStream; +import static org.apache.hive.beeline.TestBeeLineWithArgs.testCommandLineScript; import static org.junit.Assert.fail; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; -import java.io.InputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; @@ -368,27 +368,47 @@ public class TestHplSqlViaBeeLine { testScriptFile(SCRIPT_TEXT, args(), "e1=1 e2=2 e3=3 e4=4 e5=5 e6=6"); } + @Test + public void testDecimalCast() throws Throwable { + String SCRIPT_TEXT = + "DECLARE\n" + + "a DECIMAL(10,2);\n" + + "BEGIN\n" + + "SELECT CAST('10.5' AS DECIMAL(10,2)) as t INTO a;\n" + + "print (a);\n" + + "END;\n" + + "/"; + testScriptFile(SCRIPT_TEXT, args(), "10.50", OutStream.ERR); + } + + @Test + public void testNullCast() throws Throwable { + String SCRIPT_TEXT = + "BEGIN\n" + + "DECLARE a BIGINT;\n" + + "print('started');\n" + + "SELECT cast (null as BIGINT) as t INTO a\n" + + "print (a);\n" + + "print ('here');\n" + + "end;\n" + + "/"; + // Inverted match, output should not have NPE + testScriptFile(SCRIPT_TEXT, args(), "^(.(?!(NullPointerException)))*$", OutStream.ERR); + } + private static List<String> args() { return Arrays.asList("-d", BeeLine.BEELINE_DEFAULT_JDBC_DRIVER, "-u", miniHS2.getBaseJdbcURL() + ";mode=hplsql", "-n", userName); } - private static String testCommandLineScript(List<String> argList, InputStream inputStream) - throws Throwable { - BeeLine beeLine = new BeeLine(); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - PrintStream beelineOutputStream = new PrintStream(os); - beeLine.setOutputStream(beelineOutputStream); - String[] args = argList.toArray(new String[argList.size()]); - beeLine.begin(args, inputStream); - beeLine.close(); - beelineOutputStream.close(); - String output = os.toString("UTF8"); - return output; - } private void testScriptFile(String scriptText, List<String> argList, String expectedPattern) throws Throwable { + testScriptFile(scriptText, argList, expectedPattern, OutStream.OUT); + } + + private void testScriptFile(String scriptText, List<String> argList, String expectedPattern, + TestBeeLineWithArgs.OutStream outStream) throws Throwable { File scriptFile = File.createTempFile(this.getClass().getSimpleName(), "temp"); scriptFile.deleteOnExit(); try (PrintStream os = new PrintStream(new FileOutputStream(scriptFile))) { @@ -397,7 +417,7 @@ public class TestHplSqlViaBeeLine { List<String> copy = new ArrayList<>(argList); copy.add("-f"); copy.add(scriptFile.getAbsolutePath()); - String output = testCommandLineScript(copy, null); + String output = testCommandLineScript(copy, null, outStream); if (!Pattern.compile(".*" + expectedPattern + ".*", Pattern.DOTALL).matcher(output).matches()) { fail("Output: '" + output + "' should match " + expectedPattern); } diff --git a/service/src/java/org/apache/hive/service/cli/operation/hplsql/HplSqlQueryExecutor.java b/service/src/java/org/apache/hive/service/cli/operation/hplsql/HplSqlQueryExecutor.java index a1305eb12a5..9aa25d39c69 100644 --- a/service/src/java/org/apache/hive/service/cli/operation/hplsql/HplSqlQueryExecutor.java +++ b/service/src/java/org/apache/hive/service/cli/operation/hplsql/HplSqlQueryExecutor.java @@ -20,6 +20,7 @@ package org.apache.hive.service.cli.operation.hplsql; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -29,6 +30,7 @@ import java.util.Map; import org.antlr.v4.runtime.ParserRuleContext; import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.serde.serdeConstants; import org.apache.hive.hplsql.executor.ColumnMeta; import org.apache.hive.hplsql.executor.Metadata; import org.apache.hive.hplsql.executor.QueryException; @@ -120,6 +122,9 @@ public class HplSqlQueryExecutor implements QueryExecutor { @Override public <T> T get(int columnIndex, Class<T> type) { + if (current[columnIndex] == null) { + return null; + } if (type.isInstance(current[columnIndex])) { return (T) current[columnIndex]; } else { @@ -133,6 +138,12 @@ public class HplSqlQueryExecutor implements QueryExecutor { if (type == Byte.class) return type.cast(((Number) current[columnIndex]).byteValue()); } + // RowSet can never return the HiveDecimal instances created on Hive side, nor its BigDecimal representation. + // Instead, it gets converted into String object in ColumnBasedSet.addRow()... + if (type == BigDecimal.class && + serdeConstants.DECIMAL_TYPE_NAME.equalsIgnoreCase(metadata(handle).columnTypeName(columnIndex))) { + return (T) new BigDecimal((String) current[columnIndex]); + } throw new ClassCastException(current[columnIndex].getClass() + " cannot be casted to " + type); } }