IMPALA-1456: Hive UDFs with String args would crash impalad

The wrong buffer was being used.

Change-Id: I18bf9040eaeda871d1d0baee2e276749a3a38615
Reviewed-on: http://gerrit.sjc.cloudera.com:8080/5185
Reviewed-by: Casey Ching <casey@cloudera.com>
Tested-by: jenkins
This commit is contained in:
casey
2014-11-06 23:55:08 -08:00
committed by ishaan
parent 4915ea4ac9
commit 24ce8cfada
4 changed files with 28 additions and 14 deletions

View File

@@ -51,7 +51,7 @@ import com.google.common.collect.Lists;
// Wrapper object to run hive UDFs. This class works with UdfCallExpr in the
// backend to marshall data back and forth between the execution engine and
// the java UDF class.
// See the comments in be/src/exprs/udf-call-expr.h for more details.
// See the comments in be/src/exprs/hive-udf-call.h for more details.
// TODO: should we cache loaded jars and classes?
@SuppressWarnings("restriction")
public class UdfExecutor {
@@ -196,8 +196,9 @@ public class UdfExecutor {
for (int i = 0; i < argTypes_.length; ++i) {
if (UnsafeUtil.UNSAFE.getByte(inputNullsPtr_ + i) == 0) {
if (isArgString_[i]) {
Preconditions.checkState(inputArgs_[i] instanceof ImpalaBytesWritable);
inputArgs_[i] = ((ImpalaBytesWritable)inputArgs_[i]).toString();
Preconditions.checkState(inputObjects_[i] instanceof ImpalaBytesWritable);
inputArgs_[i] =
new String(((ImpalaBytesWritable)inputObjects_[i]).getBytes());
} else {
inputArgs_[i] = inputObjects_[i];
}
@@ -342,7 +343,7 @@ public class UdfExecutor {
// These objects are allocated once and reused across calls to evaluate()
private void allocateInputObjects() throws ImpalaRuntimeException {
inputObjects_ = new Writable[argTypes_.length];
inputArgs_ = new Writable[argTypes_.length];
inputArgs_ = new Object[argTypes_.length];
isArgString_ = new boolean[argTypes_.length];
for (int i = 0; i < argTypes_.length; ++i) {
@@ -378,8 +379,7 @@ public class UdfExecutor {
inputObjects_[i] = w;
} else if (method_.getParameterTypes()[i] == String.class) {
isArgString_[i] = true;
// String can be mapped to any String-like Writable class. We need
// to call toString on it before calling the UDF.
// String can be mapped to any String-like Writable class.
ImpalaBytesWritable w = new ImpalaBytesWritable(inputBufferPtr_ + offset);
inputObjects_[i] = w;
} else {

View File

@@ -71,11 +71,15 @@ double
10
====
---- QUERY
select udf_test.identity("why hello there");
# IMPALA-1456. Each "identity" call below tests a different type (BytesWritable, Text,
# and String).
select udf_test.identity("why hello there"),
udf_test.identity("why", " hello there"),
udf_test.identity("why", " hello", " there");
---- TYPES
string
string, string, string
---- RESULTS
'why hello there'
'why hello there','why hello there','why hello there'
====
---- QUERY
select udf_test.identity(NULL);
@@ -85,12 +89,13 @@ boolean
NULL
====
---- QUERY
# IMPALA-1134. Each "identity" call below tests a different type (BytesWritable and Text).
# The different types are handled slightly differently.
# IMPALA-1134. Each "identity" call below tests a different type (BytesWritable, Text,
# and String). The different types are handled slightly differently.
select length(udf_test.identity("0123456789")),
length(udf_test.identity("0123456789", "0123456789"));
length(udf_test.identity("0123456789", "0123456789")),
length(udf_test.identity("0123456789", "0123456789", "0123456789"));
---- TYPES
int, int
int, int, int
---- RESULTS
10,20
10,20,30
====

View File

@@ -16,6 +16,7 @@ drop function if exists udf_test.identity(float);
drop function if exists udf_test.identity(double);
drop function if exists udf_test.identity(string);
drop function if exists udf_test.identity(string, string);
drop function if exists udf_test.identity(string, string, string);
drop function if exists udf_test.identity(timestamp);
create database if not exists udf_test;
@@ -79,4 +80,8 @@ symbol='com.cloudera.impala.TestUdf';
create function udf_test.identity(string, string) returns string
location '/test-warehouse/impala-hive-udfs.jar'
symbol='com.cloudera.impala.TestUdf';
create function udf_test.identity(string, string, string) returns string
location '/test-warehouse/impala-hive-udfs.jar'
symbol='com.cloudera.impala.TestUdf';
====

View File

@@ -90,4 +90,8 @@ public class TestUdf extends UDF {
if (a == null || b == null) return null;
return new Text(a.toString() + b.toString());
}
public String evaluate(String a, String b, String c) {
if (a == null || b == null || c == null) return null;
return a + b + c;
}
}