This is an automated email from the ASF dual-hosted git repository.

gabriellee pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 0a228a68d6 [Improvement](javaudf) support different date argument for 
date/datetime type (#13920)
0a228a68d6 is described below

commit 0a228a68d68721ba273841b22399ee758ae44d1a
Author: Gabriel <gabrielleeb...@gmail.com>
AuthorDate: Thu Nov 3 20:33:20 2022 +0800

    [Improvement](javaudf) support different date argument for date/datetime 
type (#13920)
---
 be/src/vec/functions/function_java_udf.cpp         |  27 +-
 .../apache/doris/analysis/CreateFunctionStmt.java  |  12 +-
 .../java/org/apache/doris/udf/JdbcExecutor.java    |   4 +-
 .../java/org/apache/doris/udf/UdafExecutor.java    |  49 +++-
 .../java/org/apache/doris/udf/UdfExecutor.java     | 133 +++------
 .../main/java/org/apache/doris/udf/UdfUtils.java   | 318 ++++++++++++++++++++-
 .../data/javaudf_p0/test_javaudf_date.out          | 276 ++++++++++++++++++
 .../main/java/org/apache/doris/udf/DateTest1.java  |  28 ++
 .../main/java/org/apache/doris/udf/DateTest2.java  |  28 ++
 .../main/java/org/apache/doris/udf/DateTest3.java  |  26 ++
 .../java/org/apache/doris/udf/DateTimeTest1.java   |  28 ++
 .../java/org/apache/doris/udf/DateTimeTest2.java   |  28 ++
 .../java/org/apache/doris/udf/DateTimeTest3.java   |  28 ++
 .../main/java/org/apache/doris/udf/DoubleTest.java |  26 ++
 .../suites/javaudf_p0/test_javaudf_date.groovy     | 195 +++++++++++++
 15 files changed, 1057 insertions(+), 149 deletions(-)

diff --git a/be/src/vec/functions/function_java_udf.cpp 
b/be/src/vec/functions/function_java_udf.cpp
index 467e9e3c66..1a2a52a515 100644
--- a/be/src/vec/functions/function_java_udf.cpp
+++ b/be/src/vec/functions/function_java_udf.cpp
@@ -112,34 +112,37 @@ Status JavaFunctionCall::execute(FunctionContext* 
context, Block& block,
     JniContext* jni_ctx = reinterpret_cast<JniContext*>(
             context->get_function_state(FunctionContext::THREAD_LOCAL));
     int arg_idx = 0;
-    ColumnPtr args[arguments.size()];
+    ColumnPtr data_cols[arguments.size()];
+    ColumnPtr null_cols[arguments.size()];
     for (size_t col_idx : arguments) {
         ColumnWithTypeAndName& column = block.get_by_position(col_idx);
-        args[arg_idx] = column.column->convert_to_full_column_if_const();
+        data_cols[arg_idx] = column.column->convert_to_full_column_if_const();
         if (!_argument_types[arg_idx]->equals(*column.type)) {
             return Status::InvalidArgument(strings::Substitute(
                     "$0-th input column's type $1 does not equal to required 
type $2", arg_idx,
                     column.type->get_name(), 
_argument_types[arg_idx]->get_name()));
         }
-        if (auto* nullable = check_and_get_column<const 
ColumnNullable>(*args[arg_idx])) {
-            args[arg_idx] = nullable->get_nested_column_ptr();
-            auto null_col =
-                    
check_and_get_column<ColumnVector<UInt8>>(nullable->get_null_map_column_ptr());
-            jni_ctx->input_nulls_buffer_ptr.get()[arg_idx] =
-                    reinterpret_cast<int64_t>(null_col->get_data().data());
+        if (auto* nullable = check_and_get_column<const 
ColumnNullable>(*data_cols[arg_idx])) {
+            null_cols[arg_idx] = nullable->get_null_map_column_ptr();
+            jni_ctx->input_nulls_buffer_ptr.get()[arg_idx] = 
reinterpret_cast<int64_t>(
+                    
check_and_get_column<ColumnVector<UInt8>>(null_cols[arg_idx])
+                            ->get_data()
+                            .data());
+            data_cols[arg_idx] = nullable->get_nested_column_ptr();
         } else {
             jni_ctx->input_nulls_buffer_ptr.get()[arg_idx] = -1;
         }
 
-        if (args[arg_idx]->is_column_string()) {
-            const ColumnString* str_col = assert_cast<const 
ColumnString*>(args[arg_idx].get());
+        if (data_cols[arg_idx]->is_column_string()) {
+            const ColumnString* str_col =
+                    assert_cast<const ColumnString*>(data_cols[arg_idx].get());
             jni_ctx->input_values_buffer_ptr.get()[arg_idx] =
                     reinterpret_cast<int64_t>(str_col->get_chars().data());
             jni_ctx->input_offsets_ptrs.get()[arg_idx] =
                     reinterpret_cast<int64_t>(str_col->get_offsets().data());
-        } else if (args[arg_idx]->is_numeric() || 
args[arg_idx]->is_column_decimal()) {
+        } else if (data_cols[arg_idx]->is_numeric() || 
data_cols[arg_idx]->is_column_decimal()) {
             jni_ctx->input_values_buffer_ptr.get()[arg_idx] =
-                    
reinterpret_cast<int64_t>(args[arg_idx]->get_raw_data().data);
+                    
reinterpret_cast<int64_t>(data_cols[arg_idx]->get_raw_data().data);
         } else {
             return Status::InvalidArgument(
                     strings::Substitute("Java UDF doesn't support type $0 now 
!",
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java
index 3c47a4bc16..39fccef1dc 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java
@@ -513,6 +513,10 @@ public class CreateFunctionStmt extends DdlStmt {
         }
     }
 
+    public static final Set<Class> DATE_SUPPORTED_JAVA_TYPE = 
Sets.newHashSet(LocalDate.class, java.util.Date.class,
+            org.joda.time.LocalDate.class);
+    public static final Set<Class> DATETIME_SUPPORTED_JAVA_TYPE = 
Sets.newHashSet(LocalDateTime.class,
+            org.joda.time.DateTime.class, org.joda.time.LocalDateTime.class);
     private static final ImmutableMap<PrimitiveType, Set<Class>> 
PrimitiveTypeToJavaClassType =
             new ImmutableMap.Builder<PrimitiveType, Set<Class>>()
                     .put(PrimitiveType.BOOLEAN, Sets.newHashSet(Boolean.class, 
boolean.class))
@@ -525,10 +529,10 @@ public class CreateFunctionStmt extends DdlStmt {
                     .put(PrimitiveType.CHAR, Sets.newHashSet(String.class))
                     .put(PrimitiveType.VARCHAR, Sets.newHashSet(String.class))
                     .put(PrimitiveType.STRING, Sets.newHashSet(String.class))
-                    .put(PrimitiveType.DATE, Sets.newHashSet(LocalDate.class))
-                    .put(PrimitiveType.DATEV2, 
Sets.newHashSet(LocalDate.class))
-                    .put(PrimitiveType.DATETIME, 
Sets.newHashSet(LocalDateTime.class))
-                    .put(PrimitiveType.DATETIMEV2, 
Sets.newHashSet(LocalDateTime.class))
+                    .put(PrimitiveType.DATE, DATE_SUPPORTED_JAVA_TYPE)
+                    .put(PrimitiveType.DATEV2, DATE_SUPPORTED_JAVA_TYPE)
+                    .put(PrimitiveType.DATETIME, DATETIME_SUPPORTED_JAVA_TYPE)
+                    .put(PrimitiveType.DATETIMEV2, 
DATETIME_SUPPORTED_JAVA_TYPE)
                     .put(PrimitiveType.LARGEINT, 
Sets.newHashSet(BigInteger.class))
                     .put(PrimitiveType.DECIMALV2, 
Sets.newHashSet(BigDecimal.class))
                     .put(PrimitiveType.DECIMAL32, 
Sets.newHashSet(BigDecimal.class))
diff --git a/fe/java-udf/src/main/java/org/apache/doris/udf/JdbcExecutor.java 
b/fe/java-udf/src/main/java/org/apache/doris/udf/JdbcExecutor.java
index 49da4332c7..ffb905b7a1 100644
--- a/fe/java-udf/src/main/java/org/apache/doris/udf/JdbcExecutor.java
+++ b/fe/java-udf/src/main/java/org/apache/doris/udf/JdbcExecutor.java
@@ -175,7 +175,7 @@ public class JdbcExecutor {
 
     public long convertDateToLong(Object obj) {
         LocalDate date = ((Date) obj).toLocalDate();
-        long time = UdfUtils.convertDateTimeToLong(date.getYear(), 
date.getMonthValue(), date.getDayOfMonth(),
+        long time = UdfUtils.convertToDateTime(date.getYear(), 
date.getMonthValue(), date.getDayOfMonth(),
                 0, 0, 0, true);
         return time;
     }
@@ -188,7 +188,7 @@ public class JdbcExecutor {
         } else {
             date = ((Timestamp) obj).toLocalDateTime();
         }
-        long time = UdfUtils.convertDateTimeToLong(date.getYear(), 
date.getMonthValue(), date.getDayOfMonth(),
+        long time = UdfUtils.convertToDateTime(date.getYear(), 
date.getMonthValue(), date.getDayOfMonth(),
                 date.getHour(), date.getMinute(), date.getSecond(), false);
         return time;
     }
diff --git a/fe/java-udf/src/main/java/org/apache/doris/udf/UdafExecutor.java 
b/fe/java-udf/src/main/java/org/apache/doris/udf/UdafExecutor.java
index b0ec36882d..3e77b60f38 100644
--- a/fe/java-udf/src/main/java/org/apache/doris/udf/UdafExecutor.java
+++ b/fe/java-udf/src/main/java/org/apache/doris/udf/UdafExecutor.java
@@ -20,7 +20,7 @@ package org.apache.doris.udf;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.common.Pair;
 import org.apache.doris.thrift.TJavaUdfExecutorCtorParams;
-import org.apache.doris.udf.UdfExecutor.JavaUdfDataType;
+import org.apache.doris.udf.UdfUtils.JavaUdfDataType;
 
 import com.google.common.base.Joiner;
 import com.google.common.collect.Lists;
@@ -40,8 +40,6 @@ import java.math.BigInteger;
 import java.net.MalformedURLException;
 import java.net.URLClassLoader;
 import java.nio.charset.StandardCharsets;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -73,6 +71,8 @@ public class UdafExecutor {
     private URLClassLoader classLoader;
     private JavaUdfDataType[] argTypes;
     private JavaUdfDataType retType;
+    private Class[] argClass;
+    private Class retClass;
 
     /**
      * Constructor to create an object.
@@ -275,16 +275,22 @@ public class UdafExecutor {
                 return true;
             }
             case DATE: {
-                LocalDate date = (LocalDate) obj;
-                long time = UdfUtils.convertDateTimeToLong(date.getYear(), 
date.getMonthValue(), date.getDayOfMonth(),
-                        0, 0, 0, true);
+                long time = UdfUtils.convertToDate(obj, retClass);
                 UdfUtils.UNSAFE.putLong(UdfUtils.UNSAFE.getLong(null, 
outputBufferPtr) + row * retType.getLen(), time);
                 return true;
             }
             case DATETIME: {
-                LocalDateTime date = (LocalDateTime) obj;
-                long time = UdfUtils.convertDateTimeToLong(date.getYear(), 
date.getMonthValue(), date.getDayOfMonth(),
-                        date.getHour(), date.getMinute(), date.getSecond(), 
false);
+                long time = UdfUtils.convertToDateTime(obj, retClass);
+                UdfUtils.UNSAFE.putLong(UdfUtils.UNSAFE.getLong(null, 
outputBufferPtr) + row * retType.getLen(), time);
+                return true;
+            }
+            case DATEV2: {
+                long time = UdfUtils.convertToDateV2(obj, retClass);
+                UdfUtils.UNSAFE.putLong(UdfUtils.UNSAFE.getLong(null, 
outputBufferPtr) + row * retType.getLen(), time);
+                return true;
+            }
+            case DATETIMEV2: {
+                long time = UdfUtils.convertToDateTimeV2(obj, retClass);
                 UdfUtils.UNSAFE.putLong(UdfUtils.UNSAFE.getLong(null, 
outputBufferPtr) + row * retType.getLen(), time);
                 return true;
             }
@@ -388,13 +394,25 @@ public class UdafExecutor {
                 case DATE: {
                     long data = UdfUtils.UNSAFE.getLong(null,
                             UdfUtils.UNSAFE.getLong(null, 
UdfUtils.getAddressAtOffset(inputBufferPtrs, i)) + 8L * row);
-                    inputObjects[i] = UdfUtils.convertToDate(data);
+                    inputObjects[i] = UdfUtils.convertDateToJavaDate(data, 
argClass[i]);
                     break;
                 }
                 case DATETIME: {
                     long data = UdfUtils.UNSAFE.getLong(null,
                             UdfUtils.UNSAFE.getLong(null, 
UdfUtils.getAddressAtOffset(inputBufferPtrs, i)) + 8L * row);
-                    inputObjects[i] = UdfUtils.convertToDateTime(data);
+                    inputObjects[i] = 
UdfUtils.convertDateTimeToJavaDateTime(data, argClass[i]);
+                    break;
+                }
+                case DATEV2: {
+                    int data = UdfUtils.UNSAFE.getInt(null,
+                            UdfUtils.UNSAFE.getLong(null, 
UdfUtils.getAddressAtOffset(inputBufferPtrs, i)) + 4L * row);
+                    inputObjects[i] = UdfUtils.convertDateV2ToJavaDate(data, 
argClass[i]);
+                    break;
+                }
+                case DATETIMEV2: {
+                    long data = UdfUtils.UNSAFE.getLong(null,
+                            UdfUtils.UNSAFE.getLong(null, 
UdfUtils.getAddressAtOffset(inputBufferPtrs, i)) + 8L * row);
+                    inputObjects[i] = 
UdfUtils.convertDateTimeV2ToJavaDateTime(data, argClass[i]);
                     break;
                 }
                 case LARGEINT: {
@@ -476,20 +494,21 @@ public class UdafExecutor {
                             LOG.debug("result function set return 
parameterTypes has error");
                         } else {
                             retType = returnType.second;
+                            retClass = methods[idx].getReturnType();
                         }
                         break;
                     }
                     case UDAF_ADD_FUNCTION: {
                         allMethods.put(methods[idx].getName(), methods[idx]);
 
-                        Class<?>[] methodTypes = 
methods[idx].getParameterTypes();
-                        if (methodTypes.length != parameterTypes.length + 1) {
-                            LOG.debug("add function parameterTypes length not 
equal " + methodTypes.length + " "
+                        argClass = methods[idx].getParameterTypes();
+                        if (argClass.length != parameterTypes.length + 1) {
+                            LOG.debug("add function parameterTypes length not 
equal " + argClass.length + " "
                                     + parameterTypes.length + " " + 
methods[idx].getName());
                         }
                         if (!(parameterTypes.length == 0)) {
                             Pair<Boolean, JavaUdfDataType[]> inputType = 
UdfUtils.setArgTypes(parameterTypes,
-                                    methodTypes, true);
+                                    argClass, true);
                             if (!inputType.first) {
                                 LOG.debug("add function set arg parameterTypes 
has error");
                             } else {
diff --git a/fe/java-udf/src/main/java/org/apache/doris/udf/UdfExecutor.java 
b/fe/java-udf/src/main/java/org/apache/doris/udf/UdfExecutor.java
index fe35aec515..6f45707142 100644
--- a/fe/java-udf/src/main/java/org/apache/doris/udf/UdfExecutor.java
+++ b/fe/java-udf/src/main/java/org/apache/doris/udf/UdfExecutor.java
@@ -20,7 +20,7 @@ package org.apache.doris.udf;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.common.Pair;
 import org.apache.doris.thrift.TJavaUdfExecutorCtorParams;
-import org.apache.doris.thrift.TPrimitiveType;
+import org.apache.doris.udf.UdfUtils.JavaUdfDataType;
 
 import com.google.common.base.Joiner;
 import com.google.common.collect.Lists;
@@ -37,8 +37,6 @@ import java.math.BigInteger;
 import java.net.MalformedURLException;
 import java.net.URLClassLoader;
 import java.nio.charset.StandardCharsets;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
 
@@ -85,91 +83,7 @@ public class UdfExecutor {
     private long rowIdx;
 
     private final long batchSizePtr;
-
-    // Data types that are supported as return or argument types in Java UDFs.
-    public enum JavaUdfDataType {
-        INVALID_TYPE("INVALID_TYPE", TPrimitiveType.INVALID_TYPE, 0),
-        BOOLEAN("BOOLEAN", TPrimitiveType.BOOLEAN, 1),
-        TINYINT("TINYINT", TPrimitiveType.TINYINT, 1),
-        SMALLINT("SMALLINT", TPrimitiveType.SMALLINT, 2),
-        INT("INT", TPrimitiveType.INT, 4),
-        BIGINT("BIGINT", TPrimitiveType.BIGINT, 8),
-        FLOAT("FLOAT", TPrimitiveType.FLOAT, 4),
-        DOUBLE("DOUBLE", TPrimitiveType.DOUBLE, 8),
-        CHAR("CHAR", TPrimitiveType.CHAR, 0),
-        VARCHAR("VARCHAR", TPrimitiveType.VARCHAR, 0),
-        STRING("STRING", TPrimitiveType.STRING, 0),
-        DATE("DATE", TPrimitiveType.DATE, 8),
-        DATETIME("DATETIME", TPrimitiveType.DATETIME, 8),
-        LARGEINT("LARGEINT", TPrimitiveType.LARGEINT, 16),
-        DECIMALV2("DECIMALV2", TPrimitiveType.DECIMALV2, 16);
-
-        private final String description;
-        private final TPrimitiveType thriftType;
-        private final int len;
-
-        JavaUdfDataType(String description, TPrimitiveType thriftType, int 
len) {
-            this.description = description;
-            this.thriftType = thriftType;
-            this.len = len;
-        }
-
-        @Override
-        public String toString() {
-            return description;
-        }
-
-        public TPrimitiveType getPrimitiveType() {
-            return thriftType;
-        }
-
-        public int getLen() {
-            return len;
-        }
-
-        public static JavaUdfDataType getType(Class<?> c) {
-            if (c == boolean.class || c == Boolean.class) {
-                return JavaUdfDataType.BOOLEAN;
-            } else if (c == byte.class || c == Byte.class) {
-                return JavaUdfDataType.TINYINT;
-            } else if (c == short.class || c == Short.class) {
-                return JavaUdfDataType.SMALLINT;
-            } else if (c == int.class || c == Integer.class) {
-                return JavaUdfDataType.INT;
-            } else if (c == long.class || c == Long.class) {
-                return JavaUdfDataType.BIGINT;
-            } else if (c == float.class || c == Float.class) {
-                return JavaUdfDataType.FLOAT;
-            } else if (c == double.class || c == Double.class) {
-                return JavaUdfDataType.DOUBLE;
-            } else if (c == char.class || c == Character.class) {
-                return JavaUdfDataType.CHAR;
-            } else if (c == String.class) {
-                return JavaUdfDataType.STRING;
-            } else if (c == LocalDate.class) {
-                return JavaUdfDataType.DATE;
-            } else if (c == LocalDateTime.class) {
-                return JavaUdfDataType.DATETIME;
-            } else if (c == BigInteger.class) {
-                return JavaUdfDataType.LARGEINT;
-            } else if (c == BigDecimal.class) {
-                return JavaUdfDataType.DECIMALV2;
-            }
-            return JavaUdfDataType.INVALID_TYPE;
-        }
-
-        public static boolean isSupported(Type t) {
-            for (JavaUdfDataType javaType : JavaUdfDataType.values()) {
-                if (javaType == JavaUdfDataType.INVALID_TYPE) {
-                    continue;
-                }
-                if (javaType.getPrimitiveType() == 
t.getPrimitiveType().toThrift()) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
+    private Class[] argClass;
 
     /**
      * Create a UdfExecutor, using parameters from a serialized thrift object. 
Used by
@@ -350,17 +264,22 @@ public class UdfExecutor {
                 return true;
             }
             case DATE: {
-                LocalDate date = (LocalDate) obj;
-                long time =
-                        UdfUtils.convertDateTimeToLong(date.getYear(), 
date.getMonthValue(), date.getDayOfMonth(), 0, 0,
-                                0, true);
+                long time = UdfUtils.convertToDate(obj, 
method.getReturnType());
                 UdfUtils.UNSAFE.putLong(UdfUtils.UNSAFE.getLong(null, 
outputBufferPtr) + row * retType.getLen(), time);
                 return true;
             }
             case DATETIME: {
-                LocalDateTime date = (LocalDateTime) obj;
-                long time = UdfUtils.convertDateTimeToLong(date.getYear(), 
date.getMonthValue(), date.getDayOfMonth(),
-                        date.getHour(), date.getMinute(), date.getSecond(), 
false);
+                long time = UdfUtils.convertToDateTime(obj, 
method.getReturnType());
+                UdfUtils.UNSAFE.putLong(UdfUtils.UNSAFE.getLong(null, 
outputBufferPtr) + row * retType.getLen(), time);
+                return true;
+            }
+            case DATEV2: {
+                int time = UdfUtils.convertToDateV2(obj, 
method.getReturnType());
+                UdfUtils.UNSAFE.putInt(UdfUtils.UNSAFE.getLong(null, 
outputBufferPtr) + row * retType.getLen(), time);
+                return true;
+            }
+            case DATETIMEV2: {
+                long time = UdfUtils.convertToDateTimeV2(obj, 
method.getReturnType());
                 UdfUtils.UNSAFE.putLong(UdfUtils.UNSAFE.getLong(null, 
outputBufferPtr) + row * retType.getLen(), time);
                 return true;
             }
@@ -459,13 +378,25 @@ public class UdfExecutor {
                 case DATE: {
                     long data = UdfUtils.UNSAFE.getLong(null,
                             UdfUtils.UNSAFE.getLong(null, 
UdfUtils.getAddressAtOffset(inputBufferPtrs, i)) + 8L * row);
-                    inputObjects[i] = UdfUtils.convertToDate(data);
+                    inputObjects[i] = UdfUtils.convertDateToJavaDate(data, 
argClass[i]);
                     break;
                 }
                 case DATETIME: {
                     long data = UdfUtils.UNSAFE.getLong(null,
                             UdfUtils.UNSAFE.getLong(null, 
UdfUtils.getAddressAtOffset(inputBufferPtrs, i)) + 8L * row);
-                    inputObjects[i] = UdfUtils.convertToDateTime(data);
+                    inputObjects[i] = 
UdfUtils.convertDateTimeToJavaDateTime(data, argClass[i]);
+                    break;
+                }
+                case DATEV2: {
+                    int data = UdfUtils.UNSAFE.getInt(null,
+                            UdfUtils.UNSAFE.getLong(null, 
UdfUtils.getAddressAtOffset(inputBufferPtrs, i)) + 4L * row);
+                    inputObjects[i] = UdfUtils.convertDateV2ToJavaDate(data, 
argClass[i]);
+                    break;
+                }
+                case DATETIMEV2: {
+                    long data = UdfUtils.UNSAFE.getLong(null,
+                            UdfUtils.UNSAFE.getLong(null, 
UdfUtils.getAddressAtOffset(inputBufferPtrs, i)) + 8L * row);
+                    inputObjects[i] = 
UdfUtils.convertDateTimeV2ToJavaDateTime(data, argClass[i]);
                     break;
                 }
                 case LARGEINT: {
@@ -534,15 +465,15 @@ public class UdfExecutor {
                     continue;
                 }
                 signatures.add(m.toGenericString());
-                Class<?>[] methodTypes = m.getParameterTypes();
+                argClass = m.getParameterTypes();
 
                 // Try to match the arguments
-                if (methodTypes.length != parameterTypes.length) {
+                if (argClass.length != parameterTypes.length) {
                     continue;
                 }
                 method = m;
                 Pair<Boolean, JavaUdfDataType> returnType;
-                if (methodTypes.length == 0 && parameterTypes.length == 0) {
+                if (argClass.length == 0 && parameterTypes.length == 0) {
                     // Special case where the UDF doesn't take any input args
                     returnType = UdfUtils.setReturnType(funcRetType, 
m.getReturnType());
                     if (!returnType.first) {
@@ -560,7 +491,7 @@ public class UdfExecutor {
                 } else {
                     retType = returnType.second;
                 }
-                Pair<Boolean, JavaUdfDataType[]> inputType = 
UdfUtils.setArgTypes(parameterTypes, methodTypes, false);
+                Pair<Boolean, JavaUdfDataType[]> inputType = 
UdfUtils.setArgTypes(parameterTypes, argClass, false);
                 if (!inputType.first) {
                     continue;
                 } else {
diff --git a/fe/java-udf/src/main/java/org/apache/doris/udf/UdfUtils.java 
b/fe/java-udf/src/main/java/org/apache/doris/udf/UdfUtils.java
index dbca62a64e..00df57ccdc 100644
--- a/fe/java-udf/src/main/java/org/apache/doris/udf/UdfUtils.java
+++ b/fe/java-udf/src/main/java/org/apache/doris/udf/UdfUtils.java
@@ -17,6 +17,7 @@
 
 package org.apache.doris.udf;
 
+import org.apache.doris.analysis.CreateFunctionStmt;
 import org.apache.doris.catalog.PrimitiveType;
 import org.apache.doris.catalog.ScalarType;
 import org.apache.doris.catalog.Type;
@@ -25,22 +26,28 @@ import org.apache.doris.thrift.TPrimitiveType;
 import org.apache.doris.thrift.TScalarType;
 import org.apache.doris.thrift.TTypeDesc;
 import org.apache.doris.thrift.TTypeNode;
-import org.apache.doris.udf.UdfExecutor.JavaUdfDataType;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import org.apache.log4j.Logger;
 import sun.misc.Unsafe;
 
 import java.io.File;
 import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.time.DateTimeException;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.util.Set;
 
 public class UdfUtils {
+    private static final Logger LOG = Logger.getLogger(UdfUtils.class);
     public static final Unsafe UNSAFE;
     private static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L;
     public static final long BYTE_ARRAY_OFFSET;
@@ -59,6 +66,93 @@ public class UdfUtils {
         BYTE_ARRAY_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);
     }
 
+    // Data types that are supported as return or argument types in Java UDFs.
+    public enum JavaUdfDataType {
+        INVALID_TYPE("INVALID_TYPE", TPrimitiveType.INVALID_TYPE, 0),
+        BOOLEAN("BOOLEAN", TPrimitiveType.BOOLEAN, 1),
+        TINYINT("TINYINT", TPrimitiveType.TINYINT, 1),
+        SMALLINT("SMALLINT", TPrimitiveType.SMALLINT, 2),
+        INT("INT", TPrimitiveType.INT, 4),
+        BIGINT("BIGINT", TPrimitiveType.BIGINT, 8),
+        FLOAT("FLOAT", TPrimitiveType.FLOAT, 4),
+        DOUBLE("DOUBLE", TPrimitiveType.DOUBLE, 8),
+        CHAR("CHAR", TPrimitiveType.CHAR, 0),
+        VARCHAR("VARCHAR", TPrimitiveType.VARCHAR, 0),
+        STRING("STRING", TPrimitiveType.STRING, 0),
+        DATE("DATE", TPrimitiveType.DATE, 8),
+        DATETIME("DATETIME", TPrimitiveType.DATETIME, 8),
+        LARGEINT("LARGEINT", TPrimitiveType.LARGEINT, 16),
+        DECIMALV2("DECIMALV2", TPrimitiveType.DECIMALV2, 16),
+        DATEV2("DATEV2", TPrimitiveType.DATEV2, 4),
+        DATETIMEV2("DATETIMEV2", TPrimitiveType.DATETIMEV2, 8);
+
+        private final String description;
+        private final TPrimitiveType thriftType;
+        private final int len;
+
+        JavaUdfDataType(String description, TPrimitiveType thriftType, int 
len) {
+            this.description = description;
+            this.thriftType = thriftType;
+            this.len = len;
+        }
+
+        @Override
+        public String toString() {
+            return description;
+        }
+
+        public TPrimitiveType getPrimitiveType() {
+            return thriftType;
+        }
+
+        public int getLen() {
+            return len;
+        }
+
+        public static Set<JavaUdfDataType> getCandidateTypes(Class<?> c) {
+            if (c == boolean.class || c == Boolean.class) {
+                return Sets.newHashSet(JavaUdfDataType.BOOLEAN);
+            } else if (c == byte.class || c == Byte.class) {
+                return Sets.newHashSet(JavaUdfDataType.TINYINT);
+            } else if (c == short.class || c == Short.class) {
+                return Sets.newHashSet(JavaUdfDataType.SMALLINT);
+            } else if (c == int.class || c == Integer.class) {
+                return Sets.newHashSet(JavaUdfDataType.INT);
+            } else if (c == long.class || c == Long.class) {
+                return Sets.newHashSet(JavaUdfDataType.BIGINT);
+            } else if (c == float.class || c == Float.class) {
+                return Sets.newHashSet(JavaUdfDataType.FLOAT);
+            } else if (c == double.class || c == Double.class) {
+                return Sets.newHashSet(JavaUdfDataType.DOUBLE);
+            } else if (c == char.class || c == Character.class) {
+                return Sets.newHashSet(JavaUdfDataType.CHAR);
+            } else if (c == String.class) {
+                return Sets.newHashSet(JavaUdfDataType.STRING);
+            } else if 
(CreateFunctionStmt.DATE_SUPPORTED_JAVA_TYPE.contains(c)) {
+                return Sets.newHashSet(JavaUdfDataType.DATE, 
JavaUdfDataType.DATEV2);
+            } else if 
(CreateFunctionStmt.DATETIME_SUPPORTED_JAVA_TYPE.contains(c)) {
+                return Sets.newHashSet(JavaUdfDataType.DATETIME, 
JavaUdfDataType.DATETIMEV2);
+            } else if (c == BigInteger.class) {
+                return Sets.newHashSet(JavaUdfDataType.LARGEINT);
+            } else if (c == BigDecimal.class) {
+                return Sets.newHashSet(JavaUdfDataType.DECIMALV2);
+            }
+            return Sets.newHashSet(JavaUdfDataType.INVALID_TYPE);
+        }
+
+        public static boolean isSupported(Type t) {
+            for (JavaUdfDataType javaType : JavaUdfDataType.values()) {
+                if (javaType == JavaUdfDataType.INVALID_TYPE) {
+                    continue;
+                }
+                if (javaType.getPrimitiveType() == 
t.getPrimitiveType().toThrift()) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
     protected static Pair<Type, Integer> fromThrift(TTypeDesc typeDesc, int 
nodeIdx) throws InternalException {
         TTypeNode node = typeDesc.getTypes().get(nodeIdx);
         Type type = null;
@@ -134,14 +228,16 @@ public class UdfUtils {
         if (!JavaUdfDataType.isSupported(retType)) {
             throw new InternalException("Unsupported return type: " + 
retType.toSql());
         }
-        JavaUdfDataType javaType = JavaUdfDataType.getType(udfReturnType);
+        Set<JavaUdfDataType> javaTypes = 
JavaUdfDataType.getCandidateTypes(udfReturnType);
         // Check if the evaluate method return type is compatible with the 
return type from
         // the function definition. This happens when both of them map to the 
same primitive
         // type.
-        if (retType.getPrimitiveType().toThrift() != 
javaType.getPrimitiveType()) {
-            return Pair.of(false, javaType);
+        Object[] res = javaTypes.stream().filter(
+                t -> t.getPrimitiveType() == 
retType.getPrimitiveType().toThrift()).toArray();
+        if (res.length == 0) {
+            return Pair.of(false, (JavaUdfDataType) javaTypes.toArray()[0]);
         }
-        return Pair.of(true, javaType);
+        return Pair.of(true, (JavaUdfDataType) res[0]);
     }
 
     /**
@@ -154,18 +250,48 @@ public class UdfUtils {
         JavaUdfDataType[] inputArgTypes = new 
JavaUdfDataType[parameterTypes.length];
         int firstPos = isUdaf ? 1 : 0;
         for (int i = 0; i < parameterTypes.length; ++i) {
-            inputArgTypes[i] = JavaUdfDataType.getType(udfArgTypes[i + 
firstPos]);
-            if (inputArgTypes[i].getPrimitiveType() != 
parameterTypes[i].getPrimitiveType().toThrift()) {
+            Set<JavaUdfDataType> javaTypes = 
JavaUdfDataType.getCandidateTypes(udfArgTypes[i + firstPos]);
+            int finalI = i;
+            Object[] res = javaTypes.stream().filter(
+                    t -> t.getPrimitiveType() == 
parameterTypes[finalI].getPrimitiveType().toThrift()).toArray();
+            if (res.length == 0) {
+                inputArgTypes[i] = (JavaUdfDataType) javaTypes.toArray()[0];
                 return Pair.of(false, inputArgTypes);
+            } else {
+                inputArgTypes[i] = (JavaUdfDataType) res[0];
             }
         }
         return Pair.of(true, inputArgTypes);
     }
 
+    public static Object convertDateTimeV2ToJavaDateTime(long date, Class clz) 
{
+        int year = (int) (date >> 46);
+        int yearMonth = (int) (date >> 42);
+        int yearMonthDay = (int) (date >> 37);
+
+        int month = (yearMonth & 0XF);
+        int day = (yearMonthDay & 0X1F);
+
+        int hour = (int) ((date >> 32) & 0X1F);
+        int minute = (int) ((date >> 26) & 0X3F);
+        int second = (int) ((date >> 20) & 0X3F);
+        //here don't need those bits are type = ((minus_type_neg >> 1) & 0x7);
+
+        if (LocalDateTime.class.equals(clz)) {
+            return convertToLocalDateTime(year, month, day, hour, minute, 
second);
+        } else if (org.joda.time.DateTime.class.equals(clz)) {
+            return convertToJodaDateTime(year, month, day, hour, minute, 
second);
+        } else if (org.joda.time.LocalDateTime.class.equals(clz)) {
+            return convertToJodaLocalDateTime(year, month, day, hour, minute, 
second);
+        } else {
+            return null;
+        }
+    }
+
     /**
      * input is a 64bit num from backend, and then get year, month, day, hour, 
minus, second by the order of bits.
      */
-    public static LocalDateTime convertToDateTime(long date) {
+    public static Object convertDateTimeToJavaDateTime(long date, Class clz) {
         int year = (int) (date >> 48);
         int yearMonth = (int) (date >> 40);
         int yearMonthDay = (int) (date >> 32);
@@ -181,29 +307,149 @@ public class UdfUtils {
         int second = (minuteTypeNeg >> 4);
         //here don't need those bits are type = ((minus_type_neg >> 1) & 0x7);
 
-        LocalDateTime value = LocalDateTime.of(year, month, day, hour, minute, 
second);
+        if (LocalDateTime.class.equals(clz)) {
+            return convertToLocalDateTime(year, month, day, hour, minute, 
second);
+        } else if (org.joda.time.DateTime.class.equals(clz)) {
+            return convertToJodaDateTime(year, month, day, hour, minute, 
second);
+        } else if (org.joda.time.LocalDateTime.class.equals(clz)) {
+            return convertToJodaLocalDateTime(year, month, day, hour, minute, 
second);
+        } else {
+            return null;
+        }
+    }
+
+    public static Object convertDateV2ToJavaDate(int date, Class clz) {
+        int year = date >> 9;
+        int month = (date >> 5) & 0XF;
+        int day = date & 0X1F;
+        if (LocalDate.class.equals(clz)) {
+            return convertToLocalDate(year, month, day);
+        } else if (java.util.Date.class.equals(clz)) {
+            return convertToJavaDate(year, month, day);
+        } else if (org.joda.time.LocalDate.class.equals(clz)) {
+            return convertToJodaDate(year, month, day);
+        } else {
+            return null;
+        }
+    }
+
+    public static LocalDateTime convertToLocalDateTime(int year, int month, 
int day,
+            int hour, int minute, int second) {
+        LocalDateTime value = null;
+        try {
+            value = LocalDateTime.of(year, month, day, hour, minute, second);
+        } catch (DateTimeException e) {
+            LOG.warn("Error occurs when parsing date time value: {}", e);
+        }
         return value;
     }
 
-    /**
-     * a 64bit num convertToDate.
-     */
-    public static LocalDate convertToDate(long date) {
+    public static org.joda.time.DateTime convertToJodaDateTime(int year, int 
month, int day,
+            int hour, int minute, int second) {
+        try {
+            return new org.joda.time.DateTime(year, month, day, hour, minute, 
second);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    public static org.joda.time.LocalDateTime convertToJodaLocalDateTime(int 
year, int month, int day,
+            int hour, int minute, int second) {
+        try {
+            return new org.joda.time.LocalDateTime(year, month, day, hour, 
minute, second);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    public static Object convertDateToJavaDate(long date, Class clz) {
         int year = (int) (date >> 48);
         int yearMonth = (int) (date >> 40);
         int yearMonthDay = (int) (date >> 32);
 
         int month = (yearMonth & 0XFF);
         int day = (yearMonthDay & 0XFF);
-        LocalDate value = LocalDate.of(year, month, day);
+        if (LocalDate.class.equals(clz)) {
+            return convertToLocalDate(year, month, day);
+        } else if (java.util.Date.class.equals(clz)) {
+            return convertToJavaDate(year, month, day);
+        } else if (org.joda.time.LocalDate.class.equals(clz)) {
+            return convertToJodaDate(year, month, day);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * a 64bit num convertToDate.
+     */
+    public static LocalDate convertToLocalDate(int year, int month, int day) {
+        LocalDate value = null;
+        try {
+            value = LocalDate.of(year, month, day);
+        } catch (DateTimeException e) {
+            LOG.warn("Error occurs when parsing date value: {}", e);
+        }
         return value;
     }
 
+    public static org.joda.time.LocalDate convertToJodaDate(int year, int 
month, int day) {
+        try {
+            return new org.joda.time.LocalDate(year, month, day);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    public static java.util.Date convertToJavaDate(int year, int month, int 
day) {
+        try {
+            return new java.util.Date(year - 1900, month - 1, day);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
     /**
      * input is the second, minute, hours, day , month and year respectively.
      * and then combining all num to a 64bit value return to backend;
      */
-    public static long convertDateTimeToLong(int year, int month, int day, int 
hour, int minute, int second,
+    public static long convertToDateTime(Object obj, Class clz) {
+        if (LocalDateTime.class.equals(clz)) {
+            LocalDateTime date = (LocalDateTime) obj;
+            return convertToDateTime(date.getYear(), date.getMonthValue(), 
date.getDayOfMonth(), date.getHour(),
+                    date.getMinute(), date.getSecond(), false);
+        } else if (org.joda.time.DateTime.class.equals(clz)) {
+            org.joda.time.DateTime date = (org.joda.time.DateTime) obj;
+            return convertToDateTime(date.getYear(), date.getMonthOfYear(), 
date.getDayOfMonth(), date.getHourOfDay(),
+                    date.getMinuteOfHour(), date.getSecondOfMinute(), false);
+        } else if (org.joda.time.LocalDateTime.class.equals(clz)) {
+            org.joda.time.LocalDateTime date = (org.joda.time.LocalDateTime) 
obj;
+            return convertToDateTime(date.getYear(), date.getMonthOfYear(), 
date.getDayOfMonth(), date.getHourOfDay(),
+                    date.getMinuteOfHour(), date.getSecondOfMinute(), false);
+        } else {
+            return 0;
+        }
+    }
+
+    public static long convertToDate(Object obj, Class clz) {
+        if (LocalDate.class.equals(clz)) {
+            LocalDate date = (LocalDate) obj;
+            return convertToDateTime(date.getYear(), date.getMonthValue(), 
date.getDayOfMonth(), 0,
+                    0, 0, true);
+        } else if (java.util.Date.class.equals(clz)) {
+            java.util.Date date = (java.util.Date) obj;
+            return convertToDateTime(date.getYear() + 1900, date.getMonth(), 
date.getDay(), 0,
+                    0, 0, true);
+        } else if (org.joda.time.LocalDate.class.equals(clz)) {
+            org.joda.time.LocalDate date = (org.joda.time.LocalDate) obj;
+            return convertToDateTime(date.getYear(), date.getDayOfMonth(), 
date.getDayOfMonth(), 0,
+                    0, 0, true);
+        } else {
+            return 0;
+        }
+    }
+
+    public static long convertToDateTime(int year, int month, int day, int 
hour, int minute, int second,
             boolean isDate) {
         long time = 0;
         time = time + year;
@@ -219,6 +465,48 @@ public class UdfUtils {
         return time;
     }
 
+    public static long convertToDateTimeV2(int year, int month, int day, int 
hour, int minute, int second) {
+        return (long) second << 20 | (long) minute << 26 | (long) hour << 32
+                | (long) day << 37 | (long) month << 42 | (long) year << 46;
+    }
+
+    public static long convertToDateTimeV2(Object obj, Class clz) {
+        if (LocalDateTime.class.equals(clz)) {
+            LocalDateTime date = (LocalDateTime) obj;
+            return convertToDateTimeV2(date.getYear(), date.getMonthValue(), 
date.getDayOfMonth(), date.getHour(),
+                    date.getMinute(), date.getSecond());
+        } else if (org.joda.time.DateTime.class.equals(clz)) {
+            org.joda.time.DateTime date = (org.joda.time.DateTime) obj;
+            return convertToDateTimeV2(date.getYear(), date.getMonthOfYear(), 
date.getDayOfMonth(), date.getHourOfDay(),
+                    date.getMinuteOfHour(), date.getSecondOfMinute());
+        } else if (org.joda.time.LocalDateTime.class.equals(clz)) {
+            org.joda.time.LocalDateTime date = (org.joda.time.LocalDateTime) 
obj;
+            return convertToDateTimeV2(date.getYear(), date.getMonthOfYear(), 
date.getDayOfMonth(), date.getHourOfDay(),
+                    date.getMinuteOfHour(), date.getSecondOfMinute());
+        } else {
+            return 0;
+        }
+    }
+
+    public static int convertToDateV2(int year, int month, int day) {
+        return (int) (day | (long) month << 5 | (long) year << 9);
+    }
+
+    public static int convertToDateV2(Object obj, Class clz) {
+        if (LocalDate.class.equals(clz)) {
+            LocalDate date = (LocalDate) obj;
+            return convertToDateV2(date.getYear(), date.getMonthValue(), 
date.getDayOfMonth());
+        } else if (java.util.Date.class.equals(clz)) {
+            java.util.Date date = (java.util.Date) obj;
+            return convertToDateV2(date.getYear(), date.getMonth(), 
date.getDay());
+        } else if (org.joda.time.LocalDate.class.equals(clz)) {
+            org.joda.time.LocalDate date = (org.joda.time.LocalDate) obj;
+            return convertToDateV2(date.getYear(), date.getDayOfMonth(), 
date.getDayOfMonth());
+        } else {
+            return 0;
+        }
+    }
+
     /**
      * Change the order of the bytes, Because JVM is Big-Endian , x86 is 
Little-Endian.
      */
diff --git a/regression-test/data/javaudf_p0/test_javaudf_date.out 
b/regression-test/data/javaudf_p0/test_javaudf_date.out
new file mode 100644
index 0000000000..4fb1082ba4
--- /dev/null
+++ b/regression-test/data/javaudf_p0/test_javaudf_date.out
@@ -0,0 +1,276 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !select_default --
+1      2022-01-01      2022-01-01T11:11:11     2022-01-01      
2022-01-01T11:11:11
+1      2022-01-01      2022-01-01T11:11:11     2022-01-01      
2022-01-01T11:11:11
+1      2022-01-01      2022-01-01T11:11:11     2022-01-01      
2022-01-01T11:11:11
+1      2022-01-01      2022-01-01T11:11:11     2022-01-01      
2022-01-01T11:11:11
+1      2022-01-01      2022-01-01T11:11:11     2022-01-01      
2022-01-01T11:11:11
+1      2022-01-01      2022-01-01T11:11:11     2022-01-01      
2022-01-01T11:11:11
+1      2022-01-01      2022-01-01T11:11:11     2022-01-01      
2022-01-01T11:11:11
+1      2022-01-01      2022-01-01T11:11:11     2022-01-01      
2022-01-01T11:11:11
+1      2022-01-01      2022-01-01T11:11:11     2022-01-01      
2022-01-01T11:11:11
+
+-- !select --
+true
+true
+true
+true
+true
+true
+true
+true
+true
+
+-- !select --
+false
+false
+false
+false
+false
+false
+false
+false
+false
+
+-- !select --
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+
+-- !select --
+true
+true
+true
+true
+true
+true
+true
+true
+true
+
+-- !select --
+false
+false
+false
+false
+false
+false
+false
+false
+false
+
+-- !select --
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+
+-- !select --
+true
+true
+true
+true
+true
+true
+true
+true
+true
+
+-- !select --
+false
+false
+false
+false
+false
+false
+false
+false
+false
+
+-- !select --
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+
+-- !select --
+true
+true
+true
+true
+true
+true
+true
+true
+true
+
+-- !select --
+false
+false
+false
+false
+false
+false
+false
+false
+false
+
+-- !select --
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+
+-- !select --
+true
+true
+true
+true
+true
+true
+true
+true
+true
+
+-- !select --
+false
+false
+false
+false
+false
+false
+false
+false
+false
+
+-- !select --
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+
+-- !select --
+true
+true
+true
+true
+true
+true
+true
+true
+true
+
+-- !select --
+false
+false
+false
+false
+false
+false
+false
+false
+false
+
+-- !select --
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+\N
+
+-- !select --
+true
+true
+true
+true
+true
+true
+true
+true
+true
+
+-- !select --
+true
+true
+true
+true
+true
+true
+true
+true
+true
+
+-- !select --
+true
+true
+true
+true
+true
+true
+true
+true
+true
+
+-- !select --
+true
+true
+true
+true
+true
+true
+true
+true
+true
+
+-- !select --
+true
+true
+true
+true
+true
+true
+true
+true
+true
+
+-- !select --
+true
+true
+true
+true
+true
+true
+true
+true
+true
+
diff --git 
a/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTest1.java
 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTest1.java
new file mode 100644
index 0000000000..217bc6d48f
--- /dev/null
+++ 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTest1.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.udf;
+
+import org.apache.hadoop.hive.ql.exec.UDF;
+
+import java.time.LocalDate;
+
+public class DateTest1 extends UDF {
+    public Boolean evaluate(LocalDate date, LocalDate date2) {
+        return date == null || date2 == null ? null : date.isAfter(date2);
+    }
+}
diff --git 
a/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTest2.java
 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTest2.java
new file mode 100644
index 0000000000..05560cb474
--- /dev/null
+++ 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTest2.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.udf;
+
+import org.apache.hadoop.hive.ql.exec.UDF;
+
+import java.time.LocalDate;
+
+public class DateTest2 extends UDF {
+    public Boolean evaluate(java.util.Date date, java.util.Date date2) {
+        return date == null || date2 == null ? null : date.after(date2);
+    }
+}
diff --git 
a/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTest3.java
 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTest3.java
new file mode 100644
index 0000000000..278427f549
--- /dev/null
+++ 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTest3.java
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.udf;
+
+import org.apache.hadoop.hive.ql.exec.UDF;
+
+public class DateTest3 extends UDF {
+    public Boolean evaluate(org.joda.time.LocalDate date, 
org.joda.time.LocalDate date2) {
+        return date == null || date2 == null ? null : date.isAfter(date2);
+    }
+}
diff --git 
a/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTimeTest1.java
 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTimeTest1.java
new file mode 100644
index 0000000000..ecbbacfd7b
--- /dev/null
+++ 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTimeTest1.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.udf;
+
+import org.apache.hadoop.hive.ql.exec.UDF;
+
+import java.time.LocalDateTime;
+
+public class DateTimeTest1 extends UDF {
+    public Boolean evaluate(LocalDateTime date, LocalDateTime date2) {
+        return date == null || date2 == null ? null : date.isAfter(date2);
+    }
+}
diff --git 
a/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTimeTest2.java
 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTimeTest2.java
new file mode 100644
index 0000000000..83544313a7
--- /dev/null
+++ 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTimeTest2.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.udf;
+
+import org.apache.hadoop.hive.ql.exec.UDF;
+
+import java.time.LocalDateTime;
+
+public class DateTimeTest2 extends UDF {
+    public Boolean evaluate(org.joda.time.LocalDateTime date, 
org.joda.time.LocalDateTime date2) {
+        return date == null || date2 == null ? null : date.isAfter(date2);
+    }
+}
diff --git 
a/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTimeTest3.java
 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTimeTest3.java
new file mode 100644
index 0000000000..eeadadff6b
--- /dev/null
+++ 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DateTimeTest3.java
@@ -0,0 +1,28 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.udf;
+
+import org.apache.hadoop.hive.ql.exec.UDF;
+
+import java.time.LocalDateTime;
+
+public class DateTimeTest3 extends UDF {
+    public Boolean evaluate(org.joda.time.DateTime date, 
org.joda.time.DateTime date2) {
+        return date == null || date2 == null ? null : date.isAfter(date2);
+    }
+}
diff --git 
a/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DoubleTest.java
 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DoubleTest.java
new file mode 100644
index 0000000000..150956d8c9
--- /dev/null
+++ 
b/regression-test/java-udf-src/src/main/java/org/apache/doris/udf/DoubleTest.java
@@ -0,0 +1,26 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.udf;
+
+import org.apache.hadoop.hive.ql.exec.UDF;
+
+public class DoubleTest extends UDF {
+    public Double evaluate(Double dou,Double dou2) {
+        return dou == null || dou2 == null ? null : dou + dou2;
+    }
+}
diff --git a/regression-test/suites/javaudf_p0/test_javaudf_date.groovy 
b/regression-test/suites/javaudf_p0/test_javaudf_date.groovy
new file mode 100644
index 0000000000..a5e87b8e46
--- /dev/null
+++ b/regression-test/suites/javaudf_p0/test_javaudf_date.groovy
@@ -0,0 +1,195 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import org.codehaus.groovy.runtime.IOGroovyMethods
+
+import java.nio.charset.StandardCharsets
+import java.nio.file.Files
+import java.nio.file.Paths
+
+suite("test_javaudf_date") {
+    def tableName = "test_javaudf_date"
+    def jarPath = 
"""${context.file.parent}/jars/java-udf-case-jar-with-dependencies.jar"""
+
+    try {
+        sql """ DROP TABLE IF EXISTS ${tableName} """
+        sql """
+        CREATE TABLE IF NOT EXISTS ${tableName} (
+            `user_id` INT NOT NULL COMMENT "用户id",
+            `date_col` date NOT NULL,
+            `datetime_col` datetime NOT NULL,
+            `datev2_col` datev2 NOT NULL,
+            `datetimev2_col` datetimev2 NOT NULL
+            )
+            DISTRIBUTED BY HASH(user_id) PROPERTIES("replication_num" = "1");
+        """
+        StringBuilder sb = new StringBuilder()
+        int i = 1
+        for (; i < 9; i ++) {
+            sb.append("""
+                (1, '2022-01-01', '2022-01-01 11:11:11', '2022-01-01', 
'2022-01-01 11:11:11'),
+            """)
+        }
+        sb.append("""
+                (1, '2022-01-01', '2022-01-01 11:11:11', '2022-01-01', 
'2022-01-01 11:11:11')
+            """)
+        sql """ INSERT INTO ${tableName} VALUES
+             ${sb.toString()}
+            """
+        qt_select_default """ SELECT * FROM ${tableName} t ORDER BY user_id; 
"""
+
+        File path = new File(jarPath)
+        if (!path.exists()) {
+            throw new IllegalStateException("""${jarPath} doesn't exist! """)
+        }
+
+        sql """ CREATE FUNCTION java_udf_date_test1(date, date) RETURNS 
boolean PROPERTIES (
+            "file"="file://${jarPath}",
+            "symbol"="org.apache.doris.udf.DateTest1",
+            "type"="JAVA_UDF"
+        ); """
+
+        qt_select """ SELECT java_udf_date_test1(date_col, '2011-01-01') 
result FROM ${tableName} ORDER BY result; """
+        qt_select """ SELECT java_udf_date_test1('2011-01-01', '2011-01-01') 
result FROM ${tableName} ORDER BY result; """
+        qt_select """ SELECT java_udf_date_test1(null, '2011-01-01') result 
FROM ${tableName} ORDER BY result; """
+
+        sql """ DROP FUNCTION java_udf_date_test1(date, date); """
+
+        sql """ CREATE FUNCTION java_udf_date_test2(date, date) RETURNS 
boolean PROPERTIES (
+            "file"="file://${jarPath}",
+            "symbol"="org.apache.doris.udf.DateTest2",
+            "type"="JAVA_UDF"
+        ); """
+
+        qt_select """ SELECT java_udf_date_test2(date_col, '2011-01-01') 
result FROM ${tableName} ORDER BY result; """
+        qt_select """ SELECT java_udf_date_test2('2011-01-01', '2011-01-01') 
result FROM ${tableName} ORDER BY result; """
+        qt_select """ SELECT java_udf_date_test2(null, '2011-01-01') result 
FROM ${tableName} ORDER BY result; """
+
+        sql """ DROP FUNCTION java_udf_date_test2(date, date); """
+
+        sql """ CREATE FUNCTION java_udf_date_test3(date, date) RETURNS 
boolean PROPERTIES (
+            "file"="file://${jarPath}",
+            "symbol"="org.apache.doris.udf.DateTest3",
+            "type"="JAVA_UDF"
+        ); """
+
+        qt_select """ SELECT java_udf_date_test3(date_col, '2011-01-01') 
result FROM ${tableName} ORDER BY result; """
+        qt_select """ SELECT java_udf_date_test3('2011-01-01', '2011-01-01') 
result FROM ${tableName} ORDER BY result; """
+        qt_select """ SELECT java_udf_date_test3(null, '2011-01-01') result 
FROM ${tableName} ORDER BY result; """
+
+        sql """ DROP FUNCTION java_udf_date_test3(date, date); """
+
+        sql """ CREATE FUNCTION java_udf_datetime_test1(datetime, datetime) 
RETURNS boolean PROPERTIES (
+            "file"="file://${jarPath}",
+            "symbol"="org.apache.doris.udf.DateTimeTest1",
+            "type"="JAVA_UDF"
+        ); """
+
+        qt_select """ SELECT java_udf_datetime_test1(datetime_col, 
'2011-01-01') result FROM ${tableName} ORDER BY result; """
+        qt_select """ SELECT java_udf_datetime_test1('2011-01-01', 
'2011-01-01') result FROM ${tableName} ORDER BY result; """
+        qt_select """ SELECT java_udf_datetime_test1(null, '2011-01-01') 
result FROM ${tableName} ORDER BY result; """
+
+        sql """ DROP FUNCTION java_udf_datetime_test1(datetime, datetime); """
+
+        sql """ CREATE FUNCTION java_udf_datetime_test2(datetime, datetime) 
RETURNS boolean PROPERTIES (
+            "file"="file://${jarPath}",
+            "symbol"="org.apache.doris.udf.DateTimeTest2",
+            "type"="JAVA_UDF"
+        ); """
+
+        qt_select """ SELECT java_udf_datetime_test2(datetime_col, 
'2011-01-01') result FROM ${tableName} ORDER BY result; """
+        qt_select """ SELECT java_udf_datetime_test2('2011-01-01', 
'2011-01-01') result FROM ${tableName} ORDER BY result; """
+        qt_select """ SELECT java_udf_datetime_test2(null, '2011-01-01') 
result FROM ${tableName} ORDER BY result; """
+
+        sql """ DROP FUNCTION java_udf_datetime_test2(datetime, datetime); """
+
+        sql """ CREATE FUNCTION java_udf_datetime_test3(datetime, datetime) 
RETURNS boolean PROPERTIES (
+            "file"="file://${jarPath}",
+            "symbol"="org.apache.doris.udf.DateTimeTest3",
+            "type"="JAVA_UDF"
+        ); """
+
+        qt_select """ SELECT java_udf_datetime_test3(datetime_col, 
'2011-01-01') result FROM ${tableName} ORDER BY result; """
+        qt_select """ SELECT java_udf_datetime_test3('2011-01-01', 
'2011-01-01') result FROM ${tableName} ORDER BY result; """
+        qt_select """ SELECT java_udf_datetime_test3(null, '2011-01-01') 
result FROM ${tableName} ORDER BY result; """
+
+        sql """ DROP FUNCTION java_udf_datetime_test3(datetime, datetime); """
+
+
+        sql """ CREATE FUNCTION java_udf_datev2_test1(datev2, datev2) RETURNS 
boolean PROPERTIES (
+            "file"="file://${jarPath}",
+            "symbol"="org.apache.doris.udf.DateTest1",
+            "type"="JAVA_UDF"
+        ); """
+
+        qt_select """ SELECT java_udf_datev2_test1(datev2_col, '2011-01-01') 
result FROM ${tableName} ORDER BY result; """
+
+        sql """ DROP FUNCTION java_udf_datev2_test1(datev2, datev2); """
+
+        sql """ CREATE FUNCTION java_udf_datev2_test2(datev2, datev2) RETURNS 
boolean PROPERTIES (
+            "file"="file://${jarPath}",
+            "symbol"="org.apache.doris.udf.DateTest2",
+            "type"="JAVA_UDF"
+        ); """
+
+        qt_select """ SELECT java_udf_datev2_test2(datev2_col, '2011-01-01') 
result FROM ${tableName} ORDER BY result; """
+
+        sql """ DROP FUNCTION java_udf_datev2_test2(datev2, datev2); """
+
+        sql """ CREATE FUNCTION java_udf_datev2_test3(datev2, datev2) RETURNS 
boolean PROPERTIES (
+            "file"="file://${jarPath}",
+            "symbol"="org.apache.doris.udf.DateTest3",
+            "type"="JAVA_UDF"
+        ); """
+
+        qt_select """ SELECT java_udf_datev2_test3(datev2_col, '2011-01-01') 
result FROM ${tableName} ORDER BY result; """
+
+        sql """ DROP FUNCTION java_udf_datev2_test3(datev2, datev2); """
+
+        sql """ CREATE FUNCTION java_udf_datetimev2_test1(datetimev2, 
datetimev2) RETURNS boolean PROPERTIES (
+            "file"="file://${jarPath}",
+            "symbol"="org.apache.doris.udf.DateTimeTest1",
+            "type"="JAVA_UDF"
+        ); """
+
+        qt_select """ SELECT java_udf_datetimev2_test1(datetimev2_col, 
'2011-01-01') result FROM ${tableName} ORDER BY result; """
+
+        sql """ DROP FUNCTION java_udf_datetimev2_test1(datetimev2, 
datetimev2); """
+
+        sql """ CREATE FUNCTION java_udf_datetimev2_test2(datetimev2, 
datetimev2) RETURNS boolean PROPERTIES (
+            "file"="file://${jarPath}",
+            "symbol"="org.apache.doris.udf.DateTimeTest2",
+            "type"="JAVA_UDF"
+        ); """
+
+        qt_select """ SELECT java_udf_datetimev2_test2(datetimev2_col, 
'2011-01-01') result FROM ${tableName} ORDER BY result; """
+
+        sql """ DROP FUNCTION java_udf_datetimev2_test2(datetimev2, 
datetimev2); """
+
+        sql """ CREATE FUNCTION java_udf_datetimev2_test3(datetimev2, 
datetimev2) RETURNS boolean PROPERTIES (
+            "file"="file://${jarPath}",
+            "symbol"="org.apache.doris.udf.DateTimeTest3",
+            "type"="JAVA_UDF"
+        ); """
+
+        qt_select """ SELECT java_udf_datetimev2_test3(datetimev2_col, 
'2011-01-01') result FROM ${tableName} ORDER BY result; """
+
+        sql """ DROP FUNCTION java_udf_datetimev2_test3(datetimev2, 
datetimev2); """
+    } finally {
+        try_sql("DROP TABLE IF EXISTS ${tableName}")
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to