[imporve](udaf) refactor java-udaf executor by using for loop (#21713)

refactor java-udaf executor by using for loop
This commit is contained in:
zhangstar333
2023-07-14 11:37:19 +08:00
committed by GitHub
parent ea73dd5851
commit c07e2ada43
6 changed files with 554 additions and 406 deletions

View File

@ -41,6 +41,12 @@ under the License.
<artifactId>java-common</artifactId>
<version>${project.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.esotericsoftware/reflectasm -->
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>reflectasm</artifactId>
<version>1.11.9</version>
</dependency>
</dependencies>
<build>

View File

@ -25,12 +25,14 @@ import org.apache.doris.common.jni.utils.UdfUtils;
import org.apache.doris.common.jni.utils.UdfUtils.JavaUdfDataType;
import org.apache.doris.thrift.TJavaUdfExecutorCtorParams;
import com.google.common.base.Preconditions;
import org.apache.log4j.Logger;
import org.apache.thrift.TDeserializer;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import java.io.IOException;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
@ -1021,4 +1023,183 @@ public abstract class BaseExecutor {
protected void updateOutputOffset(long offset) {
}
public Object[] convertBasicArg(boolean isUdf, int argIdx, boolean isNullable, int rowStart, int rowEnd,
long nullMapAddr, long columnAddr, long strOffsetAddr) {
switch (argTypes[argIdx]) {
case BOOLEAN:
return UdfConvert.convertBooleanArg(isNullable, rowStart, rowEnd, nullMapAddr, columnAddr);
case TINYINT:
return UdfConvert.convertTinyIntArg(isNullable, rowStart, rowEnd, nullMapAddr, columnAddr);
case SMALLINT:
return UdfConvert.convertSmallIntArg(isNullable, rowStart, rowEnd, nullMapAddr, columnAddr);
case INT:
return UdfConvert.convertIntArg(isNullable, rowStart, rowEnd, nullMapAddr, columnAddr);
case BIGINT:
return UdfConvert.convertBigIntArg(isNullable, rowStart, rowEnd, nullMapAddr, columnAddr);
case LARGEINT:
return UdfConvert.convertLargeIntArg(isNullable, rowStart, rowEnd, nullMapAddr, columnAddr);
case FLOAT:
return UdfConvert.convertFloatArg(isNullable, rowStart, rowEnd, nullMapAddr, columnAddr);
case DOUBLE:
return UdfConvert.convertDoubleArg(isNullable, rowStart, rowEnd, nullMapAddr, columnAddr);
case CHAR:
case VARCHAR:
case STRING:
return UdfConvert
.convertStringArg(isNullable, rowStart, rowEnd, nullMapAddr, columnAddr, strOffsetAddr);
case DATE: // udaf maybe argClass[i + argClassOffset] need add +1
return UdfConvert
.convertDateArg(isUdf ? argClass[argIdx] : argClass[argIdx + 1], isNullable, rowStart, rowEnd,
nullMapAddr, columnAddr);
case DATETIME:
return UdfConvert
.convertDateTimeArg(isUdf ? argClass[argIdx] : argClass[argIdx + 1], isNullable, rowStart,
rowEnd, nullMapAddr, columnAddr);
case DATEV2:
return UdfConvert
.convertDateV2Arg(isUdf ? argClass[argIdx] : argClass[argIdx + 1], isNullable, rowStart, rowEnd,
nullMapAddr, columnAddr);
case DATETIMEV2:
return UdfConvert
.convertDateTimeV2Arg(isUdf ? argClass[argIdx] : argClass[argIdx + 1], isNullable, rowStart,
rowEnd, nullMapAddr, columnAddr);
case DECIMALV2:
case DECIMAL128:
return UdfConvert
.convertDecimalArg(argTypes[argIdx].getScale(), 16L, isNullable, rowStart, rowEnd, nullMapAddr,
columnAddr);
case DECIMAL32:
return UdfConvert
.convertDecimalArg(argTypes[argIdx].getScale(), 4L, isNullable, rowStart, rowEnd, nullMapAddr,
columnAddr);
case DECIMAL64:
return UdfConvert
.convertDecimalArg(argTypes[argIdx].getScale(), 8L, isNullable, rowStart, rowEnd, nullMapAddr,
columnAddr);
default: {
LOG.info("Not support type: " + argTypes[argIdx].toString());
Preconditions.checkState(false, "Not support type: " + argTypes[argIdx].toString());
break;
}
}
return null;
}
public Object[] convertArrayArg(int argIdx, boolean isNullable, int rowStart, int rowEnd, long nullMapAddr,
long offsetsAddr, long nestedNullMapAddr, long dataAddr, long strOffsetAddr) {
Object[] argument = (Object[]) Array.newInstance(ArrayList.class, rowEnd - rowStart);
for (int row = rowStart; row < rowEnd; ++row) {
long offsetStart = UdfUtils.UNSAFE.getLong(null, offsetsAddr + 8L * (row - 1));
long offsetEnd = UdfUtils.UNSAFE.getLong(null, offsetsAddr + 8L * (row));
int currentRowNum = (int) (offsetEnd - offsetStart);
switch (argTypes[argIdx].getItemType().getPrimitiveType()) {
case BOOLEAN: {
argument[row - rowStart] = UdfConvert
.convertArrayBooleanArg(row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case TINYINT: {
argument[row - rowStart] = UdfConvert
.convertArrayTinyIntArg(row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case SMALLINT: {
argument[row - rowStart] = UdfConvert
.convertArraySmallIntArg(row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case INT: {
argument[row - rowStart] = UdfConvert
.convertArrayIntArg(row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case BIGINT: {
argument[row - rowStart] = UdfConvert
.convertArrayBigIntArg(row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case LARGEINT: {
argument[row - rowStart] = UdfConvert
.convertArrayLargeIntArg(row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case FLOAT: {
argument[row - rowStart] = UdfConvert
.convertArrayFloatArg(row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case DOUBLE: {
argument[row - rowStart] = UdfConvert
.convertArrayDoubleArg(row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case CHAR:
case VARCHAR:
case STRING: {
argument[row - rowStart] = UdfConvert
.convertArrayStringArg(row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr, strOffsetAddr);
break;
}
case DATE: {
argument[row - rowStart] = UdfConvert
.convertArrayDateArg(row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case DATETIME: {
argument[row - rowStart] = UdfConvert
.convertArrayDateTimeArg(row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case DATEV2: {
argument[row - rowStart] = UdfConvert
.convertArrayDateV2Arg(row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case DATETIMEV2: {
argument[row - rowStart] = UdfConvert
.convertArrayDateTimeV2Arg(row, currentRowNum, offsetStart, isNullable,
nullMapAddr, nestedNullMapAddr, dataAddr);
break;
}
case DECIMALV2:
case DECIMAL128: {
argument[row - rowStart] = UdfConvert
.convertArrayDecimalArg(argTypes[argIdx].getScale(), 16L, row, currentRowNum,
offsetStart, isNullable, nullMapAddr, nestedNullMapAddr, dataAddr);
break;
}
case DECIMAL32: {
argument[row - rowStart] = UdfConvert
.convertArrayDecimalArg(argTypes[argIdx].getScale(), 4L, row, currentRowNum,
offsetStart, isNullable, nullMapAddr, nestedNullMapAddr, dataAddr);
break;
}
case DECIMAL64: {
argument[row - rowStart] = UdfConvert
.convertArrayDecimalArg(argTypes[argIdx].getScale(), 8L, row, currentRowNum,
offsetStart, isNullable, nullMapAddr, nestedNullMapAddr, dataAddr);
break;
}
default: {
LOG.info("Not support: " + argTypes[argIdx]);
Preconditions.checkState(false, "Not support type " + argTypes[argIdx].toString());
break;
}
}
}
return argument;
}
}

View File

@ -24,6 +24,7 @@ import org.apache.doris.common.jni.utils.UdfUtils;
import org.apache.doris.common.jni.utils.UdfUtils.JavaUdfDataType;
import org.apache.doris.thrift.TJavaUdfExecutorCtorParams;
import com.esotericsoftware.reflectasm.MethodAccess;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import org.apache.log4j.Logger;
@ -36,6 +37,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
/**
@ -49,6 +51,8 @@ public class UdafExecutor extends BaseExecutor {
private HashMap<String, Method> allMethods;
private HashMap<Long, Object> stateObjMap;
private Class retClass;
private int addIndex;
private MethodAccess methodAccess;
/**
* Constructor to create an object.
@ -66,6 +70,84 @@ public class UdafExecutor extends BaseExecutor {
super.close();
}
public Object[] convertBasicArguments(int argIdx, boolean isNullable, int rowStart, int rowEnd, long nullMapAddr,
long columnAddr, long strOffsetAddr) {
return convertBasicArg(false, argIdx, isNullable, rowStart, rowEnd, nullMapAddr, columnAddr, strOffsetAddr);
}
public Object[] convertArrayArguments(int argIdx, boolean isNullable, int rowStart, int rowEnd, long nullMapAddr,
long offsetsAddr, long nestedNullMapAddr, long dataAddr, long strOffsetAddr) {
return convertArrayArg(argIdx, isNullable, rowStart, rowEnd, nullMapAddr, offsetsAddr, nestedNullMapAddr,
dataAddr, strOffsetAddr);
}
public void addBatch(boolean isSinglePlace, int rowStart, int rowEnd, long placeAddr, int offset, Object[] column)
throws UdfRuntimeException {
if (isSinglePlace) {
addBatchSingle(rowStart, rowEnd, placeAddr, column);
} else {
addBatchPlaces(rowStart, rowEnd, placeAddr, offset, column);
}
}
public void addBatchSingle(int rowStart, int rowEnd, long placeAddr, Object[] column) throws UdfRuntimeException {
try {
Long curPlace = placeAddr;
Object[] inputArgs = new Object[argTypes.length + 1];
Object state = stateObjMap.get(curPlace);
if (state != null) {
inputArgs[0] = state;
} else {
Object newState = createAggState();
stateObjMap.put(curPlace, newState);
inputArgs[0] = newState;
}
Object[][] inputs = (Object[][]) column;
for (int i = 0; i < (rowEnd - rowStart); ++i) {
for (int j = 0; j < column.length; ++j) {
inputArgs[j + 1] = inputs[j][i];
}
methodAccess.invoke(udf, addIndex, inputArgs);
}
} catch (Exception e) {
LOG.warn("invoke add function meet some error: " + e.getCause().toString());
throw new UdfRuntimeException("UDAF failed to addBatchSingle: ", e);
}
}
public void addBatchPlaces(int rowStart, int rowEnd, long placeAddr, int offset, Object[] column)
throws UdfRuntimeException {
try {
Object[][] inputs = (Object[][]) column;
ArrayList<Object> placeState = new ArrayList<>(rowEnd - rowStart);
for (int row = rowStart; row < rowEnd; ++row) {
Long curPlace = UdfUtils.UNSAFE.getLong(null, placeAddr + (8L * row)) + offset;
Object state = stateObjMap.get(curPlace);
if (state != null) {
placeState.add(state);
} else {
Object newState = createAggState();
stateObjMap.put(curPlace, newState);
placeState.add(newState);
}
}
//spilt into two for loop
Object[] inputArgs = new Object[argTypes.length + 1];
for (int row = 0; row < (rowEnd - rowStart); ++row) {
inputArgs[0] = placeState.get(row);
for (int j = 0; j < column.length; ++j) {
inputArgs[j + 1] = inputs[j][row];
}
methodAccess.invoke(udf, addIndex, inputArgs);
}
} catch (Exception e) {
LOG.warn("invoke add function meet some error: " + Arrays.toString(e.getStackTrace()));
throw new UdfRuntimeException("UDAF failed to addBatchPlaces: ", e);
}
}
/**
* invoke add function, add row in loop [rowStart, rowEnd).
*/
@ -224,10 +306,10 @@ public class UdafExecutor extends BaseExecutor {
protected long getCurrentOutputOffset(long row, boolean isArrayType) {
if (isArrayType) {
return Integer.toUnsignedLong(
UdfUtils.UNSAFE.getInt(null, UdfUtils.UNSAFE.getLong(null, outputOffsetsPtr) + 8L * (row - 1)));
UdfUtils.UNSAFE.getInt(null, UdfUtils.UNSAFE.getLong(null, outputOffsetsPtr) + 8L * (row - 1)));
} else {
return Integer.toUnsignedLong(
UdfUtils.UNSAFE.getInt(null, UdfUtils.UNSAFE.getLong(null, outputOffsetsPtr) + 4L * (row - 1)));
UdfUtils.UNSAFE.getInt(null, UdfUtils.UNSAFE.getLong(null, outputOffsetsPtr) + 4L * (row - 1)));
}
}
@ -251,6 +333,7 @@ public class UdafExecutor extends BaseExecutor {
loader = ClassLoader.getSystemClassLoader();
}
Class<?> c = Class.forName(className, true, loader);
methodAccess = MethodAccess.get(c);
Constructor<?> ctor = c.getConstructor();
udf = ctor.newInstance();
Method[] methods = c.getDeclaredMethods();
@ -281,7 +364,7 @@ public class UdafExecutor extends BaseExecutor {
}
case UDAF_ADD_FUNCTION: {
allMethods.put(methods[idx].getName(), methods[idx]);
addIndex = methodAccess.getIndex(UDAF_ADD_FUNCTION);
argClass = methods[idx].getParameterTypes();
if (argClass.length != parameterTypes.length + 1) {
LOG.debug("add function parameterTypes length not equal " + argClass.length + " "

View File

@ -37,263 +37,269 @@ import java.util.Arrays;
public class UdfConvert {
private static final Logger LOG = Logger.getLogger(UdfConvert.class);
public static Object[] convertBooleanArg(boolean isNullable, int numRows, long nullMapAddr, long columnAddr) {
Boolean[] argument = new Boolean[numRows];
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i] = UdfUtils.UNSAFE.getBoolean(null, columnAddr + i);
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
argument[i] = UdfUtils.UNSAFE.getBoolean(null, columnAddr + i);
}
}
return argument;
}
public static Object[] convertTinyIntArg(boolean isNullable, int numRows, long nullMapAddr, long columnAddr) {
Byte[] argument = new Byte[numRows];
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i] = UdfUtils.UNSAFE.getByte(null, columnAddr + i);
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
argument[i] = UdfUtils.UNSAFE.getByte(null, columnAddr + i);
}
}
return argument;
}
public static Object[] convertSmallIntArg(boolean isNullable, int numRows, long nullMapAddr, long columnAddr) {
Short[] argument = new Short[numRows];
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i] = UdfUtils.UNSAFE.getShort(null, columnAddr + (i * 2L));
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
argument[i] = UdfUtils.UNSAFE.getShort(null, columnAddr + (i * 2L));
}
}
return argument;
}
public static Object[] convertIntArg(boolean isNullable, int numRows, long nullMapAddr, long columnAddr) {
Integer[] argument = new Integer[numRows];
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i] = UdfUtils.UNSAFE.getInt(null, columnAddr + (i * 4L));
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
argument[i] = UdfUtils.UNSAFE.getInt(null, columnAddr + (i * 4L));
}
}
return argument;
}
public static Object[] convertBigIntArg(boolean isNullable, int numRows, long nullMapAddr, long columnAddr) {
Long[] argument = new Long[numRows];
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i] = UdfUtils.UNSAFE.getLong(null, columnAddr + (i * 8L));
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
argument[i] = UdfUtils.UNSAFE.getLong(null, columnAddr + (i * 8L));
}
}
return argument;
}
public static Object[] convertFloatArg(boolean isNullable, int numRows, long nullMapAddr, long columnAddr) {
Float[] argument = new Float[numRows];
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i] = UdfUtils.UNSAFE.getFloat(null, columnAddr + (i * 4L));
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
argument[i] = UdfUtils.UNSAFE.getFloat(null, columnAddr + (i * 4L));
}
}
return argument;
}
public static Object[] convertDoubleArg(boolean isNullable, int numRows, long nullMapAddr, long columnAddr) {
Double[] argument = new Double[numRows];
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i] = UdfUtils.UNSAFE.getDouble(null, columnAddr + (i * 8L));
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
argument[i] = UdfUtils.UNSAFE.getDouble(null, columnAddr + (i * 8L));
}
}
return argument;
}
public static Object[] convertDateArg(Class argTypeClass, boolean isNullable, int numRows, long nullMapAddr,
public static Object[] convertBooleanArg(boolean isNullable, int rowsStart, int rowsEnd, long nullMapAddr,
long columnAddr) {
Object[] argument = (Object[]) Array.newInstance(argTypeClass, numRows);
Boolean[] argument = new Boolean[rowsEnd - rowsStart];
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getBoolean(null, columnAddr + i);
} // else is the current row is null
}
} else {
for (int i = rowsStart; i < rowsEnd; ++i) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getBoolean(null, columnAddr + i);
}
}
return argument;
}
public static Object[] convertTinyIntArg(boolean isNullable, int rowsStart, int rowsEnd, long nullMapAddr,
long columnAddr) {
Byte[] argument = new Byte[rowsEnd - rowsStart];
if (isNullable) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getByte(null, columnAddr + i);
} // else is the current row is null
}
} else {
for (int i = rowsStart; i < rowsEnd; ++i) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getByte(null, columnAddr + i);
}
}
return argument;
}
public static Object[] convertSmallIntArg(boolean isNullable, int rowsStart, int rowsEnd, long nullMapAddr,
long columnAddr) {
Short[] argument = new Short[rowsEnd - rowsStart];
if (isNullable) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getShort(null, columnAddr + (i * 2L));
} // else is the current row is null
}
} else {
for (int i = rowsStart; i < rowsEnd; ++i) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getShort(null, columnAddr + (i * 2L));
}
}
return argument;
}
public static Object[] convertIntArg(boolean isNullable, int rowsStart, int rowsEnd, long nullMapAddr,
long columnAddr) {
Integer[] argument = new Integer[rowsEnd - rowsStart];
if (isNullable) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getInt(null, columnAddr + (i * 4L));
} // else is the current row is null
}
} else {
for (int i = rowsStart; i < rowsEnd; ++i) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getInt(null, columnAddr + (i * 4L));
}
}
return argument;
}
public static Object[] convertBigIntArg(boolean isNullable, int rowsStart, int rowsEnd, long nullMapAddr,
long columnAddr) {
Long[] argument = new Long[rowsEnd - rowsStart];
if (isNullable) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getLong(null, columnAddr + (i * 8L));
} // else is the current row is null
}
} else {
for (int i = rowsStart; i < rowsEnd; ++i) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getLong(null, columnAddr + (i * 8L));
}
}
return argument;
}
public static Object[] convertFloatArg(boolean isNullable, int rowsStart, int rowsEnd, long nullMapAddr,
long columnAddr) {
Float[] argument = new Float[rowsEnd - rowsStart];
if (isNullable) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getFloat(null, columnAddr + (i * 4L));
} // else is the current row is null
}
} else {
for (int i = rowsStart; i < rowsEnd; ++i) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getFloat(null, columnAddr + (i * 4L));
}
}
return argument;
}
public static Object[] convertDoubleArg(boolean isNullable, int rowsStart, int rowsEnd, long nullMapAddr,
long columnAddr) {
Double[] argument = new Double[rowsEnd - rowsStart];
if (isNullable) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getDouble(null, columnAddr + (i * 8L));
} // else is the current row is null
}
} else {
for (int i = rowsStart; i < rowsEnd; ++i) {
argument[i - rowsStart] = UdfUtils.UNSAFE.getDouble(null, columnAddr + (i * 8L));
}
}
return argument;
}
public static Object[] convertDateArg(Class argTypeClass, boolean isNullable, int rowsStart, int rowsEnd,
long nullMapAddr, long columnAddr) {
Object[] argument = (Object[]) Array.newInstance(argTypeClass, rowsEnd - rowsStart);
if (isNullable) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
long value = UdfUtils.UNSAFE.getLong(null, columnAddr + (i * 8L));
argument[i] = UdfUtils.convertDateToJavaDate(value, argTypeClass);
argument[i - rowsStart] = UdfUtils.convertDateToJavaDate(value, argTypeClass);
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
for (int i = rowsStart; i < rowsEnd; ++i) {
long value = UdfUtils.UNSAFE.getLong(null, columnAddr + (i * 8L));
argument[i] = UdfUtils.convertDateToJavaDate(value, argTypeClass);
argument[i - rowsStart] = UdfUtils.convertDateToJavaDate(value, argTypeClass);
}
}
return argument;
}
public static Object[] convertDateTimeArg(Class argTypeClass, boolean isNullable, int numRows, long nullMapAddr,
long columnAddr) {
Object[] argument = (Object[]) Array.newInstance(argTypeClass, numRows);
public static Object[] convertDateTimeArg(Class argTypeClass, boolean isNullable, int rowsStart, int rowsEnd,
long nullMapAddr, long columnAddr) {
Object[] argument = (Object[]) Array.newInstance(argTypeClass, rowsEnd - rowsStart);
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
long value = UdfUtils.UNSAFE.getLong(null, columnAddr + (i * 8L));
argument[i] = UdfUtils
argument[i - rowsStart] = UdfUtils
.convertDateTimeToJavaDateTime(value, argTypeClass);
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
for (int i = rowsStart; i < rowsEnd; ++i) {
long value = UdfUtils.UNSAFE.getLong(null, columnAddr + (i * 8L));
argument[i] = UdfUtils.convertDateTimeToJavaDateTime(value, argTypeClass);
argument[i - rowsStart] = UdfUtils.convertDateTimeToJavaDateTime(value, argTypeClass);
}
}
return argument;
}
public static Object[] convertDateV2Arg(Class argTypeClass, boolean isNullable, int numRows, long nullMapAddr,
long columnAddr) {
Object[] argument = (Object[]) Array.newInstance(argTypeClass, numRows);
public static Object[] convertDateV2Arg(Class argTypeClass, boolean isNullable, int rowsStart, int rowsEnd,
long nullMapAddr, long columnAddr) {
Object[] argument = (Object[]) Array.newInstance(argTypeClass, rowsEnd - rowsStart);
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
int value = UdfUtils.UNSAFE.getInt(null, columnAddr + (i * 4L));
argument[i] = UdfUtils.convertDateV2ToJavaDate(value, argTypeClass);
argument[i - rowsStart] = UdfUtils.convertDateV2ToJavaDate(value, argTypeClass);
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
for (int i = rowsStart; i < rowsEnd; ++i) {
int value = UdfUtils.UNSAFE.getInt(null, columnAddr + (i * 4L));
argument[i] = UdfUtils.convertDateV2ToJavaDate(value, argTypeClass);
argument[i - rowsStart] = UdfUtils.convertDateV2ToJavaDate(value, argTypeClass);
}
}
return argument;
}
public static Object[] convertDateTimeV2Arg(Class argTypeClass, boolean isNullable, int numRows, long nullMapAddr,
long columnAddr) {
Object[] argument = (Object[]) Array.newInstance(argTypeClass, numRows);
public static Object[] convertDateTimeV2Arg(Class argTypeClass, boolean isNullable, int rowsStart, int rowsEnd,
long nullMapAddr, long columnAddr) {
Object[] argument = (Object[]) Array.newInstance(argTypeClass, rowsEnd - rowsStart);
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(null, nullMapAddr + i) == 0) {
long value = UdfUtils.UNSAFE.getLong(columnAddr + (i * 8L));
argument[i] = UdfUtils
argument[i - rowsStart] = UdfUtils
.convertDateTimeV2ToJavaDateTime(value, argTypeClass);
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
for (int i = rowsStart; i < rowsEnd; ++i) {
long value = UdfUtils.UNSAFE.getLong(null, columnAddr + (i * 8L));
argument[i] = UdfUtils
argument[i - rowsStart] = UdfUtils
.convertDateTimeV2ToJavaDateTime(value, argTypeClass);
}
}
return argument;
}
public static Object[] convertLargeIntArg(boolean isNullable, int numRows, long nullMapAddr, long columnAddr) {
BigInteger[] argument = new BigInteger[numRows];
public static Object[] convertLargeIntArg(boolean isNullable, int rowsStart, int rowsEnd, long nullMapAddr,
long columnAddr) {
BigInteger[] argument = new BigInteger[rowsEnd - rowsStart];
byte[] bytes = new byte[16];
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
UdfUtils.copyMemory(null, columnAddr + (i * 16L), bytes, UdfUtils.BYTE_ARRAY_OFFSET, 16);
argument[i] = new BigInteger(UdfUtils.convertByteOrder(bytes));
argument[i - rowsStart] = new BigInteger(UdfUtils.convertByteOrder(bytes));
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
for (int i = rowsStart; i < rowsEnd; ++i) {
UdfUtils.copyMemory(null, columnAddr + (i * 16L), bytes, UdfUtils.BYTE_ARRAY_OFFSET, 16);
argument[i] = new BigInteger(UdfUtils.convertByteOrder(bytes));
argument[i - rowsStart] = new BigInteger(UdfUtils.convertByteOrder(bytes));
}
}
return argument;
}
public static Object[] convertDecimalArg(int scale, long typeLen, boolean isNullable, int numRows, long nullMapAddr,
long columnAddr) {
BigDecimal[] argument = new BigDecimal[numRows];
public static Object[] convertDecimalArg(int scale, long typeLen, boolean isNullable, int rowsStart, int rowsEnd,
long nullMapAddr, long columnAddr) {
BigDecimal[] argument = new BigDecimal[rowsEnd - rowsStart];
byte[] bytes = new byte[(int) typeLen];
if (isNullable) {
for (int i = 0; i < numRows; ++i) {
for (int i = rowsStart; i < rowsEnd; ++i) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + i) == 0) {
UdfUtils.copyMemory(null, columnAddr + (i * typeLen), bytes, UdfUtils.BYTE_ARRAY_OFFSET, typeLen);
BigInteger bigInteger = new BigInteger(UdfUtils.convertByteOrder(bytes));
argument[i] = new BigDecimal(bigInteger, scale); //show to pass scale info
argument[i - rowsStart] = new BigDecimal(bigInteger, scale); //show to pass scale info
} // else is the current row is null
}
} else {
for (int i = 0; i < numRows; ++i) {
for (int i = rowsStart; i < rowsEnd; ++i) {
UdfUtils.copyMemory(null, columnAddr + (i * typeLen), bytes, UdfUtils.BYTE_ARRAY_OFFSET, typeLen);
BigInteger bigInteger = new BigInteger(UdfUtils.convertByteOrder(bytes));
argument[i] = new BigDecimal(bigInteger, scale);
argument[i - rowsStart] = new BigDecimal(bigInteger, scale);
}
}
return argument;
}
public static Object[] convertStringArg(boolean isNullable, int numRows, long nullMapAddr,
public static Object[] convertStringArg(boolean isNullable, int rowsStart, int rowsEnd, long nullMapAddr,
long charsAddr, long offsetsAddr) {
String[] argument = new String[numRows];
String[] argument = new String[rowsEnd - rowsStart];
Preconditions.checkState(UdfUtils.UNSAFE.getInt(null, offsetsAddr + 4L * (0 - 1)) == 0,
"offsetsAddr[-1] should be 0;");
final int totalLen = UdfUtils.UNSAFE.getInt(null, offsetsAddr + (rowsEnd - 1) * 4L);
byte[] bytes = new byte[totalLen];
UdfUtils.copyMemory(null, charsAddr, bytes, UdfUtils.BYTE_ARRAY_OFFSET, totalLen);
if (isNullable) {
for (int row = 0; row < numRows; ++row) {
for (int row = rowsStart; row < rowsEnd; ++row) {
if (UdfUtils.UNSAFE.getByte(nullMapAddr + row) == 0) {
int offset = UdfUtils.UNSAFE.getInt(null, offsetsAddr + row * 4L);
int numBytes = offset - UdfUtils.UNSAFE.getInt(null, offsetsAddr + 4L * (row - 1));
long base = charsAddr + offset - numBytes;
byte[] bytes = new byte[numBytes];
UdfUtils.copyMemory(null, base, bytes, UdfUtils.BYTE_ARRAY_OFFSET, numBytes);
argument[row] = new String(bytes, StandardCharsets.UTF_8);
int prevOffset = UdfUtils.UNSAFE.getInt(null, offsetsAddr + 4L * (row - 1));
int currOffset = UdfUtils.UNSAFE.getInt(null, offsetsAddr + row * 4L);
argument[row - rowsStart] = new String(bytes, prevOffset, currOffset - prevOffset,
StandardCharsets.UTF_8);
} // else is the current row is null
}
} else {
for (int row = 0; row < numRows; ++row) {
int offset = UdfUtils.UNSAFE.getInt(null, offsetsAddr + row * 4L);
int numBytes = offset - UdfUtils.UNSAFE.getInt(null, offsetsAddr + 4L * (row - 1));
long base = charsAddr + offset - numBytes;
byte[] bytes = new byte[numBytes];
UdfUtils.copyMemory(null, base, bytes, UdfUtils.BYTE_ARRAY_OFFSET, numBytes);
argument[row] = new String(bytes, StandardCharsets.UTF_8);
for (int row = rowsStart; row < rowsEnd; ++row) {
int prevOffset = UdfUtils.UNSAFE.getInt(null, offsetsAddr + 4L * (row - 1));
int currOffset = UdfUtils.UNSAFE.getInt(null, offsetsAddr + 4L * row);
argument[row - rowsStart] = new String(bytes, prevOffset, currOffset - prevOffset,
StandardCharsets.UTF_8);
}
}
return argument;
@ -1314,7 +1320,7 @@ public class UdfConvert {
}
//////////////////////////////////////////convertArray///////////////////////////////////////////////////////////
public static void convertArrayBooleanArg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<Boolean> convertArrayBooleanArg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<Boolean> data = null;
if (isNullable) {
@ -1340,10 +1346,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArrayTinyIntArg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<Byte> convertArrayTinyIntArg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<Byte> data = null;
if (isNullable) {
@ -1369,10 +1375,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArraySmallIntArg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<Short> convertArraySmallIntArg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<Short> data = null;
if (isNullable) {
@ -1398,10 +1404,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArrayIntArg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<Integer> convertArrayIntArg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<Integer> data = null;
if (isNullable) {
@ -1427,10 +1433,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArrayBigIntArg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<Long> convertArrayBigIntArg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<Long> data = null;
if (isNullable) {
@ -1456,10 +1462,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArrayFloatArg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<Float> convertArrayFloatArg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<Float> data = null;
if (isNullable) {
@ -1485,10 +1491,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArrayDoubleArg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<Double> convertArrayDoubleArg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<Double> data = null;
if (isNullable) {
@ -1514,10 +1520,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArrayDateArg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<LocalDate> convertArrayDateArg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<LocalDate> data = null;
if (isNullable) {
@ -1549,10 +1555,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArrayDateTimeArg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<LocalDateTime> convertArrayDateTimeArg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<LocalDateTime> data = null;
if (isNullable) {
@ -1582,10 +1588,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArrayDateV2Arg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<LocalDate> convertArrayDateV2Arg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<LocalDate> data = null;
if (isNullable) {
@ -1613,10 +1619,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArrayDateTimeV2Arg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<LocalDateTime> convertArrayDateTimeV2Arg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<LocalDateTime> data = null;
if (isNullable) {
@ -1646,10 +1652,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArrayLargeIntArg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<BigInteger> convertArrayLargeIntArg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<BigInteger> data = null;
byte[] bytes = new byte[16];
@ -1678,10 +1684,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArrayDecimalArg(int scale, long typeLen, Object[] argument, int row, int currentRowNum,
public static ArrayList<BigDecimal> convertArrayDecimalArg(int scale, long typeLen, int row, int currentRowNum,
long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr) {
ArrayList<BigDecimal> data = null;
@ -1713,10 +1719,10 @@ public class UdfConvert {
}
} // for loop
} // end for all current row
argument[row] = data;
return data;
}
public static void convertArrayStringArg(Object[] argument, int row, int currentRowNum, long offsetStart,
public static ArrayList<String> convertArrayStringArg(int row, int currentRowNum, long offsetStart,
boolean isNullable, long nullMapAddr, long nestedNullMapAddr, long dataAddr, long strOffsetAddr) {
ArrayList<String> data = null;
if (isNullable) {
@ -1755,6 +1761,6 @@ public class UdfConvert {
}
}
}
argument[row] = data;
return data;
}
}

View File

@ -24,6 +24,7 @@ import org.apache.doris.common.jni.utils.UdfUtils;
import org.apache.doris.common.jni.utils.UdfUtils.JavaUdfDataType;
import org.apache.doris.thrift.TJavaUdfExecutorCtorParams;
import com.esotericsoftware.reflectasm.MethodAccess;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
@ -50,6 +51,8 @@ public class UdfExecutor extends BaseExecutor {
private long rowIdx;
private long batchSizePtr;
private int evaluateIndex;
private MethodAccess methodAccess;
/**
* Create a UdfExecutor, using parameters from a serialized thrift object. Used by
@ -113,166 +116,14 @@ public class UdfExecutor extends BaseExecutor {
public Object[] convertBasicArguments(int argIdx, boolean isNullable, int numRows, long nullMapAddr,
long columnAddr, long strOffsetAddr) {
switch (argTypes[argIdx]) {
case BOOLEAN:
return UdfConvert.convertBooleanArg(isNullable, numRows, nullMapAddr, columnAddr);
case TINYINT:
return UdfConvert.convertTinyIntArg(isNullable, numRows, nullMapAddr, columnAddr);
case SMALLINT:
return UdfConvert.convertSmallIntArg(isNullable, numRows, nullMapAddr, columnAddr);
case INT:
return UdfConvert.convertIntArg(isNullable, numRows, nullMapAddr, columnAddr);
case BIGINT:
return UdfConvert.convertBigIntArg(isNullable, numRows, nullMapAddr, columnAddr);
case LARGEINT:
return UdfConvert.convertLargeIntArg(isNullable, numRows, nullMapAddr, columnAddr);
case FLOAT:
return UdfConvert.convertFloatArg(isNullable, numRows, nullMapAddr, columnAddr);
case DOUBLE:
return UdfConvert.convertDoubleArg(isNullable, numRows, nullMapAddr, columnAddr);
case CHAR:
case VARCHAR:
case STRING:
return UdfConvert.convertStringArg(isNullable, numRows, nullMapAddr, columnAddr, strOffsetAddr);
case DATE: // udaf maybe argClass[i + argClassOffset] need add +1
return UdfConvert.convertDateArg(argClass[argIdx], isNullable, numRows, nullMapAddr, columnAddr);
case DATETIME:
return UdfConvert.convertDateTimeArg(argClass[argIdx], isNullable, numRows, nullMapAddr, columnAddr);
case DATEV2:
return UdfConvert.convertDateV2Arg(argClass[argIdx], isNullable, numRows, nullMapAddr, columnAddr);
case DATETIMEV2:
return UdfConvert.convertDateTimeV2Arg(argClass[argIdx], isNullable, numRows, nullMapAddr, columnAddr);
case DECIMALV2:
case DECIMAL128:
return UdfConvert.convertDecimalArg(argTypes[argIdx].getScale(), 16L, isNullable, numRows, nullMapAddr,
columnAddr);
case DECIMAL32:
return UdfConvert.convertDecimalArg(argTypes[argIdx].getScale(), 4L, isNullable, numRows, nullMapAddr,
columnAddr);
case DECIMAL64:
return UdfConvert.convertDecimalArg(argTypes[argIdx].getScale(), 8L, isNullable, numRows, nullMapAddr,
columnAddr);
default: {
LOG.info("Not support type: " + argTypes[argIdx].toString());
Preconditions.checkState(false, "Not support type: " + argTypes[argIdx].toString());
break;
}
}
return null;
return convertBasicArg(true, argIdx, isNullable, 0, numRows, nullMapAddr, columnAddr, strOffsetAddr);
}
public Object[] convertArrayArguments(int argIdx, boolean isNullable, int numRows, long nullMapAddr,
long offsetsAddr, long nestedNullMapAddr, long dataAddr, long strOffsetAddr) {
Object[] argument = (Object[]) Array.newInstance(ArrayList.class, numRows);
for (int row = 0; row < numRows; ++row) {
long offsetStart = UdfUtils.UNSAFE.getLong(null, offsetsAddr + 8L * (row - 1));
long offsetEnd = UdfUtils.UNSAFE.getLong(null, offsetsAddr + 8L * (row));
int currentRowNum = (int) (offsetEnd - offsetStart);
switch (argTypes[argIdx].getItemType().getPrimitiveType()) {
case BOOLEAN: {
UdfConvert
.convertArrayBooleanArg(argument, row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case TINYINT: {
UdfConvert
.convertArrayTinyIntArg(argument, row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case SMALLINT: {
UdfConvert
.convertArraySmallIntArg(argument, row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case INT: {
UdfConvert.convertArrayIntArg(argument, row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case BIGINT: {
UdfConvert.convertArrayBigIntArg(argument, row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case LARGEINT: {
UdfConvert
.convertArrayLargeIntArg(argument, row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case FLOAT: {
UdfConvert.convertArrayFloatArg(argument, row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case DOUBLE: {
UdfConvert.convertArrayDoubleArg(argument, row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case CHAR:
case VARCHAR:
case STRING: {
UdfConvert.convertArrayStringArg(argument, row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr, strOffsetAddr);
break;
}
case DATE: {
UdfConvert.convertArrayDateArg(argument, row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case DATETIME: {
UdfConvert
.convertArrayDateTimeArg(argument, row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case DATEV2: {
UdfConvert.convertArrayDateV2Arg(argument, row, currentRowNum, offsetStart, isNullable, nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case DATETIMEV2: {
UdfConvert.convertArrayDateTimeV2Arg(argument, row, currentRowNum, offsetStart, isNullable,
nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case DECIMALV2:
case DECIMAL128: {
UdfConvert.convertArrayDecimalArg(argTypes[argIdx].getScale(), 16L, argument, row, currentRowNum,
offsetStart, isNullable,
nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case DECIMAL32: {
UdfConvert.convertArrayDecimalArg(argTypes[argIdx].getScale(), 4L, argument, row, currentRowNum,
offsetStart, isNullable,
nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
case DECIMAL64: {
UdfConvert.convertArrayDecimalArg(argTypes[argIdx].getScale(), 8L, argument, row, currentRowNum,
offsetStart, isNullable,
nullMapAddr,
nestedNullMapAddr, dataAddr);
break;
}
default: {
LOG.info("Not support: " + argTypes[argIdx]);
Preconditions.checkState(false, "Not support type " + argTypes[argIdx].toString());
break;
}
}
}
return argument;
return convertArrayArg(argIdx, isNullable, 0, numRows, nullMapAddr, offsetsAddr, nestedNullMapAddr, dataAddr,
strOffsetAddr);
}
/**
@ -287,7 +138,7 @@ public class UdfExecutor extends BaseExecutor {
for (int j = 0; j < column.length; ++j) {
parameters[j] = inputs[j][i];
}
result[i] = method.invoke(udf, parameters);
result[i] = methodAccess.invoke(udf, evaluateIndex, parameters);
}
return result;
} catch (Exception e) {
@ -581,6 +432,7 @@ public class UdfExecutor extends BaseExecutor {
loader = ClassLoader.getSystemClassLoader();
}
Class<?> c = Class.forName(className, true, loader);
methodAccess = MethodAccess.get(c);
Constructor<?> ctor = c.getConstructor();
udf = ctor.newInstance();
Method[] methods = c.getMethods();
@ -597,6 +449,7 @@ public class UdfExecutor extends BaseExecutor {
continue;
}
method = m;
evaluateIndex = methodAccess.getIndex(UDF_FUNCTION_NAME);
Pair<Boolean, JavaUdfDataType> returnType;
if (argClass.length == 0 && parameterTypes.length == 0) {
// Special case where the UDF doesn't take any input args