[UDF] Fix bug that UDF can't handle constant null value (#2914)
This CL modify the `evalExpr()` of ExpressionFunctions, so that it won't change the `FunctionCallExpr` to `NullLiteral` when there is null parameter in UDF. Which will fix the problem described in ISSUE: #2913
This commit is contained in:
@ -40,8 +40,6 @@ public class BatchRollupJobTest {
|
||||
|
||||
private static String runningDir = "fe/mocked/BatchRollupJobTest/" + UUID.randomUUID().toString() + "/";
|
||||
|
||||
private static ConnectContext ctx = UtFrameUtils.createDefaultCtx();
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws Exception {
|
||||
UtFrameUtils.createMinDorisCluster(runningDir);
|
||||
@ -49,7 +47,7 @@ public class BatchRollupJobTest {
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
System.out.println("xxx");
|
||||
ConnectContext ctx = UtFrameUtils.createDefaultCtx();
|
||||
// create database db1
|
||||
String createDbStmtStr = "create database db1;";
|
||||
CreateDbStmt createDbStmt = (CreateDbStmt) UtFrameUtils.parseAndAnalyzeStmt(createDbStmtStr, ctx);
|
||||
|
||||
@ -0,0 +1,105 @@
|
||||
// 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.catalog;
|
||||
|
||||
import org.apache.doris.analysis.CreateDbStmt;
|
||||
import org.apache.doris.analysis.CreateFunctionStmt;
|
||||
import org.apache.doris.analysis.Expr;
|
||||
import org.apache.doris.analysis.FunctionCallExpr;
|
||||
import org.apache.doris.common.jmockit.Deencapsulation;
|
||||
import org.apache.doris.planner.PlanFragment;
|
||||
import org.apache.doris.planner.Planner;
|
||||
import org.apache.doris.planner.UnionNode;
|
||||
import org.apache.doris.qe.ConnectContext;
|
||||
import org.apache.doris.qe.QueryState;
|
||||
import org.apache.doris.qe.StmtExecutor;
|
||||
import org.apache.doris.utframe.UtFrameUtils;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/*
|
||||
* Author: Chenmingyu
|
||||
* Date: Feb 16, 2020
|
||||
*/
|
||||
|
||||
public class CreateFunctionTest {
|
||||
|
||||
private static String runningDir = "fe/mocked/CreateFunctionTest/" + UUID.randomUUID().toString() + "/";
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws Exception {
|
||||
UtFrameUtils.createMinDorisCluster(runningDir);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void teardown() {
|
||||
File file = new File("fe/mocked/CreateFunctionTest/");
|
||||
file.delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
ConnectContext ctx = UtFrameUtils.createDefaultCtx();
|
||||
|
||||
// create database db1
|
||||
String createDbStmtStr = "create database db1;";
|
||||
CreateDbStmt createDbStmt = (CreateDbStmt) UtFrameUtils.parseAndAnalyzeStmt(createDbStmtStr, ctx);
|
||||
Catalog.getCurrentCatalog().createDb(createDbStmt);
|
||||
System.out.println(Catalog.getCurrentCatalog().getDbNames());
|
||||
|
||||
Database db = Catalog.getCurrentCatalog().getDb("default_cluster:db1");
|
||||
Assert.assertNotNull(db);
|
||||
|
||||
String createFuncStr = "create function db1.my_add(VARCHAR(1024)) RETURNS BOOLEAN properties\n" +
|
||||
"(\n" +
|
||||
"\"symbol\" = \"_ZN9doris_udf6AddUdfEPNS_15FunctionContextERKNS_9StringValE\",\n" +
|
||||
"\"prepare_fn\" = \"_ZN9doris_udf13AddUdfPrepareEPNS_15FunctionContextENS0_18FunctionStateScopeE\",\n" +
|
||||
"\"close_fn\" = \"_ZN9doris_udf11AddUdfCloseEPNS_15FunctionContextENS0_18FunctionStateScopeE\",\n" +
|
||||
"\"object_file\" = \"http://nmg01-inf-dorishb00.nmg01.baidu.com:8456/libcmy_udf.so\"\n" +
|
||||
");";
|
||||
|
||||
CreateFunctionStmt createFunctionStmt = (CreateFunctionStmt) UtFrameUtils.parseAndAnalyzeStmt(createFuncStr, ctx);
|
||||
Catalog.getCurrentCatalog().createFunction(createFunctionStmt);
|
||||
|
||||
List<Function> functions = db.getFunctions();
|
||||
Assert.assertEquals(1, functions.size());
|
||||
Assert.assertTrue(functions.get(0).isUdf());
|
||||
|
||||
String queryStr = "select db1.my_add(null)";
|
||||
ctx.getState().reset();
|
||||
StmtExecutor stmtExecutor = new StmtExecutor(ctx, queryStr);
|
||||
stmtExecutor.execute();
|
||||
Assert.assertNotEquals(QueryState.MysqlStateType.ERR, ctx.getState().getStateType());
|
||||
Planner planner = stmtExecutor.planner();
|
||||
Assert.assertEquals(1, planner.getFragments().size());
|
||||
PlanFragment fragment = planner.getFragments().get(0);
|
||||
Assert.assertTrue(fragment.getPlanRoot() instanceof UnionNode);
|
||||
UnionNode unionNode = (UnionNode)fragment.getPlanRoot();
|
||||
List<List<Expr>> constExprLists = Deencapsulation.getField(unionNode, "constExprLists_");
|
||||
Assert.assertEquals(1, constExprLists.size());
|
||||
Assert.assertEquals(1, constExprLists.get(0).size());
|
||||
Assert.assertTrue(constExprLists.get(0).get(0) instanceof FunctionCallExpr);
|
||||
}
|
||||
}
|
||||
@ -42,6 +42,7 @@ import com.google.common.collect.Maps;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
@ -49,8 +50,9 @@ import java.util.Random;
|
||||
public class UtFrameUtils {
|
||||
|
||||
// Help to create a mocked ConnectContext.
|
||||
public static ConnectContext createDefaultCtx() {
|
||||
ConnectContext ctx = new ConnectContext();
|
||||
public static ConnectContext createDefaultCtx() throws IOException {
|
||||
SocketChannel channel = SocketChannel.open();
|
||||
ConnectContext ctx = new ConnectContext(channel);
|
||||
ctx.setCluster(SystemInfoService.DEFAULT_CLUSTER);
|
||||
ctx.setCurrentUserIdentity(UserIdentity.ROOT);
|
||||
ctx.setQualifiedUser(PaloAuth.ROOT_USER);
|
||||
|
||||
Reference in New Issue
Block a user