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 <[email protected]>
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);
}
}