1219 lines
74 KiB
C++
1219 lines
74 KiB
C++
/**
|
|
* Copyright (c) 2021 OceanBase
|
|
* OceanBase CE is licensed under Mulan PubL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
|
* You may obtain a copy of Mulan PubL v2 at:
|
|
* http://license.coscl.org.cn/MulanPubL-2.0
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PubL v2 for more details.
|
|
*/
|
|
|
|
#ifndef _OB_EXPR_TEST_UTILS_H
|
|
#define _OB_EXPR_TEST_UTILS_H 1
|
|
#define USING_LOG_PREFIX SQL_ENG
|
|
#include <math.h>
|
|
#include "sql/engine/expr/ob_expr_equal.h"
|
|
#include "lib/number/ob_number_v2.h"
|
|
#include "lib/oblog/ob_log.h"
|
|
#include "lib/charset/ob_dtoa.h"
|
|
#include "share/object/ob_obj_cast.h"
|
|
enum MyBool
|
|
{
|
|
MY_TRUE,
|
|
MY_FALSE,
|
|
MY_NULL,
|
|
MY_ERROR
|
|
};
|
|
static oceanbase::common::ObArenaAllocator g_alloc_;
|
|
|
|
#define TEST_OPERATOR(expr_op) \
|
|
class Test##expr_op : public expr_op \
|
|
{ \
|
|
public:\
|
|
Test##expr_op() : expr_op(g_alloc_) {}\
|
|
~Test##expr_op() {}\
|
|
}
|
|
|
|
#define EV 0.00001
|
|
#define LOGIC_ERROR2(cmp_op, str_buf, func, type1, v1, type2, v2, res) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj vres; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = op.func(vres, t1, t2, expr_ctx); \
|
|
ASSERT_EQ(res, err); \
|
|
} while(0)
|
|
|
|
#define COMPARE_EXPECT_INNER(cmp_op, collation, str_buf, func, type1, v1, type2, v2, res) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj vres; \
|
|
cmp_op op(g_alloc_); \
|
|
ObExprResType res_type; \
|
|
res_type.set_collation_level(CS_LEVEL_EXPLICIT); \
|
|
res_type.set_collation_type(collation); \
|
|
op.set_result_type(res_type); \
|
|
t1.set_##type1(v1); \
|
|
t1.set_collation_type(collation); \
|
|
t2.set_##type2(v2); \
|
|
t2.set_collation_type(collation); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
res_type.set_calc_type(ObVarcharType); \
|
|
res_type.set_calc_collation_type(collation); \
|
|
op.set_result_type(res_type); \
|
|
int err = op.func(vres, t1, t2, expr_ctx); \
|
|
if (res == MY_ERROR) { \
|
|
ASSERT_NE(OB_SUCCESS, err); \
|
|
} else { \
|
|
ASSERT_EQ(OB_SUCCESS, err); \
|
|
OB_LOG(INFO, "after calc", K(vres), K(t1), K(t2)); \
|
|
switch(res) { \
|
|
case MY_TRUE: \
|
|
ASSERT_TRUE(vres.is_true()); \
|
|
break; \
|
|
case MY_FALSE: \
|
|
ASSERT_TRUE(vres.is_false()); \
|
|
break; \
|
|
case MY_NULL: \
|
|
ASSERT_TRUE(vres.is_null()); \
|
|
default: \
|
|
break; \
|
|
} \
|
|
} \
|
|
} while(0)
|
|
|
|
#define COMPARE_EXPECT(cmp_op, str_buf, func, type1, v1, type2, v2, res) \
|
|
COMPARE_EXPECT_INNER(cmp_op, CS_TYPE_BINARY, str_buf, func, type1, v1, type2, v2, res)
|
|
#define COMPARE_EXPECT_BIN(cmp_op, str_buf, func, type1, v1, type2, v2, res) \
|
|
COMPARE_EXPECT_INNER(cmp_op, CS_TYPE_UTF8MB4_BIN, str_buf, func, type1, v1, type2, v2, res)
|
|
#define COMPARE_EXPECT_GEN(cmp_op, str_buf, func, type1, v1, type2, v2, res) \
|
|
COMPARE_EXPECT_INNER(cmp_op, CS_TYPE_UTF8MB4_GENERAL_CI, str_buf, func, type1, v1, type2, v2, res)
|
|
|
|
#define LOGIC_ERROR3(cmp_op, str_buf, func, type1, v1, type2, v2, type3, v3, res) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj t3; \
|
|
ObObj vres; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
t3.set_##type3(v3); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = op.func(vres, t1, t2, t3, expr_ctx); \
|
|
ASSERT_EQ(res, err); \
|
|
} while(0)
|
|
|
|
#define COMPARE3_EXPECT(cmp_op, str_buf, func, type1, v1, type2, v2, type3, v3, res) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj t3; \
|
|
ObObj vres; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
t3.set_##type3(v3); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = op.func(vres, t1, t2, t3, expr_ctx); \
|
|
if (res == MY_ERROR) \
|
|
{ \
|
|
ASSERT_NE(OB_SUCCESS, err); \
|
|
} \
|
|
else \
|
|
{ \
|
|
ASSERT_EQ(OB_SUCCESS, err); \
|
|
switch(res) \
|
|
{ \
|
|
case MY_TRUE: \
|
|
ASSERT_TRUE(vres.is_true()); \
|
|
break; \
|
|
case MY_FALSE: \
|
|
ASSERT_TRUE(vres.is_false()); \
|
|
break; \
|
|
default: \
|
|
ASSERT_TRUE(vres.is_null()); \
|
|
break; \
|
|
} \
|
|
}\
|
|
} while(0)
|
|
|
|
// bad design, need remove
|
|
#define STR_FUNC_EXPECT(str_op_object, func, type1, v1, type2, v2, res) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj vres; \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
int err = str_op_object.func(vres, t1, t2); \
|
|
ASSERT_EQ(OB_SUCCESS, err); \
|
|
switch(res) \
|
|
{ \
|
|
case MY_TRUE: \
|
|
ASSERT_TRUE(vres.is_true()); \
|
|
break; \
|
|
case MY_FALSE: \
|
|
ASSERT_TRUE(vres.is_false()); \
|
|
break; \
|
|
default: \
|
|
ASSERT_TRUE(vres.is_null()); \
|
|
break; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define LOGIC_EXPECT2(cmp_op, str_buf, func, type1, v1, type2, v2, rtype, res) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj vres; \
|
|
bool bv; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = op.func(vres, t1, t2, expr_ctx); \
|
|
if (OB_SUCCESS == err)\
|
|
{\
|
|
ASSERT_EQ(rtype, vres.get_type()); \
|
|
if (ObBoolType == rtype) \
|
|
{ \
|
|
ASSERT_EQ(OB_SUCCESS, vres.get_bool(bv)); \
|
|
ASSERT_EQ(res, bv); \
|
|
} \
|
|
}\
|
|
else \
|
|
{\
|
|
ASSERT_EQ(res, err); \
|
|
}\
|
|
}while(0)
|
|
|
|
// bad design, need remove
|
|
#define STR_FUNC_EXPECT(str_op_object, func, type1, v1, type2, v2, res) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj vres; \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
int err = str_op_object.func(vres, t1, t2); \
|
|
ASSERT_EQ(OB_SUCCESS, err); \
|
|
switch(res) \
|
|
{ \
|
|
case MY_TRUE: \
|
|
ASSERT_TRUE(vres.is_true()); \
|
|
break; \
|
|
case MY_FALSE: \
|
|
ASSERT_TRUE(vres.is_false()); \
|
|
break; \
|
|
default: \
|
|
ASSERT_TRUE(vres.is_null()); \
|
|
break; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define LOGIC_EXPECT3(cmp_op, str_buf, func, type1, v1, type2, v2, type3, v3, rtype, res) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj t3; \
|
|
ObObj vres; \
|
|
bool bv; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
t3.set_##type3(v3); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = op.func(vres, t1, t2, t3, expr_ctx); \
|
|
if (OB_SUCCESS == err)\
|
|
{ \
|
|
ASSERT_EQ(rtype, vres.get_type()); \
|
|
if (ObBoolType == rtype) \
|
|
{ \
|
|
ASSERT_EQ(OB_SUCCESS, vres.get_bool(bv)); \
|
|
ASSERT_EQ(res, bv); \
|
|
} \
|
|
} \
|
|
else \
|
|
{ \
|
|
ASSERT_EQ(res, err); \
|
|
} \
|
|
} while(0)
|
|
#define LOGIC_GENPARAM1(params, type1, v1) \
|
|
params[0].set_##type1(v1);
|
|
#define LOGIC_GENPARAM2(params, type1, v1, type2, v2) \
|
|
params[0].set_##type1(v1); \
|
|
params[1].set_##type2(v2)
|
|
|
|
#define LOGIC_GENPARAM3(params, type1, v1, type2, v2, type3, v3) \
|
|
LOGIC_GENPARAM2(params, type1, v1, type2, v2); \
|
|
params[2].set_##type3(v3)
|
|
|
|
#define LOGIC_GENPARAM4(params, type1, v1, type2, v2, type3, v3, type4, v4) \
|
|
LOGIC_GENPARAM3(params, type1, v1, type2, v2, type3, v3); \
|
|
params[3].set_##type4(v4)
|
|
|
|
#define LOGIC_GENPARAM5(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5) \
|
|
LOGIC_GENPARAM4(params, type1, v1, type2, v2, type3, v3, type4, v4); \
|
|
params[4].set_##type5(v5)
|
|
|
|
#define LOGIC_GENPARAM6(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6) \
|
|
LOGIC_GENPARAM5(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5); \
|
|
params[5].set_##type6(v6)
|
|
|
|
#define LOGIC_GENPARAM7(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7) \
|
|
LOGIC_GENPARAM6(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6); \
|
|
params[6].set_##type7(v7)
|
|
|
|
#define LOGIC_GENPARAM8(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7, type8, v8) \
|
|
LOGIC_GENPARAM7(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7); \
|
|
params[7].set_##type8(v8)
|
|
|
|
#define LOGIC_GENPARAM9(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7, type8, v8, type9, v9) \
|
|
LOGIC_GENPARAM8(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7, type8, v8); \
|
|
params[8].set_##type9(v9)
|
|
|
|
#define LOGIC_GENPARAM10(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7, type8, v8, type9, v9, type10, v10) \
|
|
LOGIC_GENPARAM9(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7, type8, v8, type9, v9); \
|
|
params[9].set_##type10(v10)
|
|
|
|
#define LOGIC_GENPARAM11(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7, type8, v8, type9, v9, type10, v10, type11, v11) \
|
|
LOGIC_GENPARAM10(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7, type8, v8, type9, v9, type10, v10); \
|
|
params[10].set_##type11(v11)
|
|
|
|
#define LOGIC_GENPARAM12(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7, type8, v8, type9, v9, type10, v10, type11, v11, type12, v12) \
|
|
LOGIC_GENPARAM11(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7, type8, v8, type9, v9, type10, v10, type11, v11); \
|
|
params[11].set_##type12(v12)
|
|
#define LOGIC_GENPARAM13(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7, type8, v8, type9, v9, type10, v10, type11, v11, type12, v12, type13, v13) \
|
|
LOGIC_GENPARAM12(params, type1, v1, type2, v2, type3, v3, type4, v4, type5, v5, type6, v6, type7, v7, type8, v8, type9, v9, type10, v10, type11, v11, type12, v12); \
|
|
params[12].set_##type13(v13)
|
|
|
|
#define LOGIC_GENTYPE2(params, t1, t2) \
|
|
params[0].set_type(t1); \
|
|
params[1].set_type(t2)
|
|
|
|
#define LOGIC_GENTYPE3(params, t1, t2, t3) \
|
|
LOGIC_GENTYPE2(params, t1, t2); \
|
|
params[2].set_type(t3)
|
|
|
|
#define LOGIC_GENTYPE4(params, t1, t2, t3, t4) \
|
|
LOGIC_GENTYPE3(params, t1, t2, t3); \
|
|
params[3].set_type(t4)
|
|
|
|
#define LOGIC_GENTYPE5(params, t1, t2, t3, t4, t5) \
|
|
LOGIC_GENTYPE4(params, t1, t2, t3, t4); \
|
|
params[4].set_type(t5)
|
|
|
|
#define LOGIC_GENTYPE6(params, t1, t2, t3, t4, t5, t6) \
|
|
LOGIC_GENTYPE5(params, t1, t2, t3, t4, t5); \
|
|
params[5].set_type(t6)
|
|
|
|
#define LOGIC_EXPECTN(cmp_op, num, rtype, res, ...) \
|
|
do { \
|
|
ObObj vres; \
|
|
cmp_op op(g_alloc_); \
|
|
bool bv; \
|
|
ObObj params[num]; \
|
|
LOGIC_GENPARAM##num(params, __VA_ARGS__); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = op.calc_resultN(vres, params, num, expr_ctx); \
|
|
if (OB_SUCCESS == err)\
|
|
{ \
|
|
ASSERT_EQ(rtype, vres.get_type()); \
|
|
if (ObBoolType == rtype) \
|
|
{ \
|
|
ASSERT_EQ(OB_SUCCESS, vres.get_bool(bv)); \
|
|
ASSERT_EQ(res, bv); \
|
|
} \
|
|
} \
|
|
else \
|
|
{ \
|
|
ASSERT_EQ(res, err); \
|
|
} \
|
|
} while(0)
|
|
|
|
#define LOGIC_EXPECT_TYPE2(cmp_op, func, type1, type2, res) \
|
|
do { \
|
|
ObExprResType t1; \
|
|
ObExprResType t2; \
|
|
ObExprResType vres; \
|
|
ObExprTypeCtx ctx; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_type(type1); \
|
|
t2.set_type(type2); \
|
|
int err = op.func(vres, t1, t2, ctx); \
|
|
if (OB_SUCCESS == err) \
|
|
{ \
|
|
ASSERT_EQ(res, vres.get_type()); \
|
|
} \
|
|
else \
|
|
{ \
|
|
ASSERT_EQ(res, err); \
|
|
} \
|
|
}while(0)
|
|
|
|
#define LOGIC_EXPECT_TYPE3(cmp_op, func, type1, type2, type3, res) \
|
|
do { \
|
|
ObExprResType t1; \
|
|
ObExprResType t2; \
|
|
ObExprResType t3; \
|
|
ObExprResType vres; \
|
|
ObExprTypeCtx ctx; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_type(type1); \
|
|
t2.set_type(type2); \
|
|
t3.set_type(type3); \
|
|
int err = op.func(vres, t1, t2, t3, ctx); \
|
|
if (OB_SUCCESS == err) \
|
|
{ \
|
|
ASSERT_EQ(res, vres.get_type()); \
|
|
} \
|
|
else \
|
|
{ \
|
|
ASSERT_EQ(res, err); \
|
|
} \
|
|
}while(0)
|
|
|
|
#define LOGIC_EXPECT_TYPEN(cmp_op, num, res, ...) \
|
|
do { \
|
|
ObExprResType vres; \
|
|
ObExprTypeCtx ctx; \
|
|
cmp_op op(g_alloc_); \
|
|
ObExprResType params[num]; \
|
|
LOGIC_GENTYPE##num(params, __VA_ARGS__); \
|
|
int err = op.calc_result_typeN(vres, params, num, ctx); \
|
|
if (OB_SUCCESS == err) \
|
|
{ \
|
|
ASSERT_EQ(res, vres.get_type()); \
|
|
} \
|
|
else \
|
|
{ \
|
|
ASSERT_EQ(res, err); \
|
|
} \
|
|
} while(0)
|
|
|
|
#define ARITH_EXPECT_TYPE_WITH_ROW(cmp_op, func, type1, type2, res) \
|
|
do { \
|
|
ObExprResType t1; \
|
|
ObExprResType t2; \
|
|
ObExprResType vres; \
|
|
ObExprTypeCtx ctx; \
|
|
cmp_op op(g_alloc_); \
|
|
op.set_row_dimension(1); \
|
|
t1.set_type(type1); \
|
|
t2.set_type(type2); \
|
|
int err = op.func(vres, t1, t2, ctx); \
|
|
ASSERT_EQ(res, err); \
|
|
}while(0)
|
|
|
|
#define ARITH_EXPECT_TYPE(cmp_op, func, type1, type2, res) \
|
|
do { \
|
|
ObExprResType t1; \
|
|
ObExprResType t2; \
|
|
ObExprResType vres; \
|
|
ObExprTypeCtx ctx; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_type(type1); \
|
|
t2.set_type(type2); \
|
|
int err = op.func(vres, t1, t2, ctx); \
|
|
ASSERT_EQ(OB_SUCCESS, err); \
|
|
ASSERT_EQ(res, vres.get_type()); \
|
|
}while(0)
|
|
|
|
#define ARITH_EXPECT_TYPE_OBJ(cmp_op,str_buf, func, obj1, obj2, res) \
|
|
do { \
|
|
ObObj vres; \
|
|
cmp_op op(g_alloc_); \
|
|
int err = op.func(vres, obj1, obj2,str_buf); \
|
|
ASSERT_EQ(OB_SUCCESS, err); \
|
|
ASSERT_EQ(res, vres.get_type()); \
|
|
}while(0)
|
|
|
|
#define ARITH_EXPECT_TYPE3(cmp_op, func, type1, type2, type3, res) \
|
|
do { \
|
|
ObExprResType t1; \
|
|
ObExprResType t2; \
|
|
ObExprResType t3; \
|
|
ObExprResType vres; \
|
|
ObExprTypeCtx ctx; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_type(type1); \
|
|
t2.set_type(type2); \
|
|
t3.set_type(type3); \
|
|
if (type1 == ObVarcharType) { \
|
|
t1.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
t1.set_collation_level(CS_LEVEL_EXPLICIT); \
|
|
} \
|
|
if (type2 == ObVarcharType) { \
|
|
t2.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
t2.set_collation_level(CS_LEVEL_EXPLICIT); \
|
|
} \
|
|
if (type3 == ObVarcharType) { \
|
|
t3.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
t3.set_collation_level(CS_LEVEL_EXPLICIT); \
|
|
} \
|
|
OB_LOG(INFO, "set type", K(t1),K(t2),K(t3)); \
|
|
int err = op.func(vres, t1, t2, t3, ctx); \
|
|
ASSERT_EQ(OB_SUCCESS, err); \
|
|
ASSERT_EQ(res, vres.get_type()); \
|
|
}while(0)
|
|
|
|
#define ARITH_EXPECT_TYPE_ERROR(cmp_op, func, type1, type2) \
|
|
do { \
|
|
ObExprResType t1; \
|
|
ObExprResType t2; \
|
|
ObExprResType vres; \
|
|
ObExprTypeCtx ctx; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_type(type1); \
|
|
t2.set_type(type2); \
|
|
int err = op.func(vres, t1, t2, ctx); \
|
|
ASSERT_EQ(OB_ERR_INVALID_TYPE_FOR_OP, err); \
|
|
}while(0)
|
|
|
|
#define ARITH_EXPECT_TYPE_ERROR3(cmp_op, func, type1, type2, type3) \
|
|
do { \
|
|
ObExprResType t1; \
|
|
ObExprResType t2; \
|
|
ObExprResType t3; \
|
|
ObExprResType vres; \
|
|
ObExprTypeCtx ctx; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_type(type1); \
|
|
t2.set_type(type2); \
|
|
t3.set_type(type3); \
|
|
int err = op.func(vres, t1, t2, t3, ctx); \
|
|
ASSERT_EQ(OB_INVALID_ARGUMENT, err); \
|
|
}while(0)
|
|
|
|
#define ARITH_EXPECT_TYPE_ERROR4(cmp_op, func, type1, type2, type3) \
|
|
do { \
|
|
ObExprResType t1; \
|
|
ObExprResType t2; \
|
|
ObExprResType t3; \
|
|
ObExprResType vres; \
|
|
ObExprTypeCtx ctx; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_type(type1); \
|
|
t2.set_type(type2); \
|
|
t3.set_type(type3); \
|
|
int err = op.func(vres, t1, t2, t3, ctx); \
|
|
ASSERT_EQ(OB_ERR_UNEXPECTED, err); \
|
|
}while(0)
|
|
|
|
#define ARITH_ERROR(cmp_op, str_buf, func, type1, v1, type2, v2, res) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj vres; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = op.func(vres, t1, t2, expr_ctx); \
|
|
ASSERT_EQ(res, err); \
|
|
}while(0)
|
|
#define ARITH_EXPECT_ERROR(cmp_op, str_buf, func, t1, v1, t2, v2) \
|
|
do { \
|
|
ObObj ob1; \
|
|
ObObj ob2; \
|
|
ObObj vres; \
|
|
cmp_op op(g_alloc_); \
|
|
ob1.set_##t1(v1); \
|
|
ob2.set_##t2(v2); \
|
|
int ret = op.func(vres, ob1, ob2, str_buf, -1); \
|
|
EXPECT_TRUE(OB_FAIL(ret)); \
|
|
} while(0)
|
|
|
|
#define ARITH_EXPECT_OBJ(cmp_op, str_buf, func, type1, v1, type2, v2, rt, rv) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj vres; \
|
|
ObObj resf; \
|
|
cmp_op op(g_alloc_); \
|
|
resf.set_##rt(rv); \
|
|
t1.set_##type1(v1); \
|
|
t1.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
t2.set_##type2(v2); \
|
|
t2.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
int ret = op.func(vres, t1, t2, str_buf, -1); \
|
|
OB_LOG(DEBUG, "after calc", K(t1), K(t2), K(vres), K(resf)); \
|
|
EXPECT_TRUE(OB_SUCC(ret)); \
|
|
if (vres.get_type() == ObDoubleType || vres.get_type() == ObFloatType) { \
|
|
} else { \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(resf, vres, CS_TYPE_UTF8MB4_BIN, CO_EQ));\
|
|
}\
|
|
} while(0)
|
|
|
|
#define ARITH_EXPECT(cmp_op, str_buf, func, type1, v1, type2, v2, res) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj vres; \
|
|
cmp_op op(g_alloc_);\
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
int err = op.func(vres, t1, t2, str_buf, -1); \
|
|
if (OB_SUCCESS != err) \
|
|
{ \
|
|
ASSERT_EQ(res, err); \
|
|
} \
|
|
else \
|
|
{ \
|
|
switch(vres.get_type()) \
|
|
{ \
|
|
case ObIntType: \
|
|
ASSERT_EQ(res, vres.get_int()); \
|
|
break; \
|
|
case ObUInt64Type: \
|
|
ASSERT_EQ(res, vres.get_uint64()); \
|
|
break; \
|
|
case ObFloatType: \
|
|
ASSERT_TRUE(fabsf(res-vres.get_float()<EV)); \
|
|
break; \
|
|
case ObDoubleType: \
|
|
ASSERT_TRUE(fabs(res - vres.get_double())<EV); \
|
|
break; \
|
|
case ObNumberType: \
|
|
{ \
|
|
number::ObNumber res_nmb; \
|
|
res_nmb.from(#res, *(str_buf)); \
|
|
ASSERT_STREQ(res_nmb.format(), vres.get_number().format()); \
|
|
break; \
|
|
} \
|
|
case ObMaxType: \
|
|
ASSERT_EQ(res, vres.get_type()); \
|
|
break; \
|
|
case ObNullType: \
|
|
ASSERT_EQ(res, vres.get_type()); \
|
|
default: \
|
|
ASSERT_TRUE(vres.is_null()); \
|
|
break; \
|
|
} \
|
|
} \
|
|
} while(0)
|
|
|
|
#define ROW1_COMPARE_EXPECT(cmp_op, str_buf, func, type1, v1, type2, v2, res) \
|
|
do { \
|
|
ObObj t1[1]; \
|
|
ObObj t2[1]; \
|
|
ObObj vres; \
|
|
cmp_op op(g_alloc_); \
|
|
t1[0].set_##type1(v1); \
|
|
t2[0].set_##type2(v2); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = op.func(vres, t1, t2, 1, expr_ctx); \
|
|
ASSERT_EQ(OB_SUCCESS, err); \
|
|
switch(res) \
|
|
{ \
|
|
case MY_TRUE: \
|
|
ASSERT_TRUE(vres.is_true()); \
|
|
break; \
|
|
case MY_FALSE: \
|
|
ASSERT_TRUE(vres.is_false()); \
|
|
break; \
|
|
default: \
|
|
ASSERT_TRUE(vres.is_null()); \
|
|
break; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define ROW2_COMPARE_EXPECT(cmp_op, str_buf, func, type11, v11, type12, v12, type21, v21, type22, v22, res) \
|
|
do { \
|
|
ObObj t1[2]; \
|
|
ObObj t2[2]; \
|
|
ObObj vres; \
|
|
cmp_op op(g_alloc_); \
|
|
t1[0].set_##type11(v11); \
|
|
t1[1].set_##type12(v12); \
|
|
t2[0].set_##type21(v21); \
|
|
t2[1].set_##type22(v22); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = op.func(vres, t1, t2, 2, expr_ctx); \
|
|
ASSERT_EQ(OB_SUCCESS, err); \
|
|
switch(res) \
|
|
{ \
|
|
case MY_TRUE: \
|
|
ASSERT_TRUE(vres.is_true()); \
|
|
break; \
|
|
case MY_FALSE: \
|
|
ASSERT_TRUE(vres.is_false()); \
|
|
break; \
|
|
default: \
|
|
ASSERT_TRUE(vres.is_null()); \
|
|
break; \
|
|
} \
|
|
} while(0)
|
|
|
|
#define EXPECT_FAIL_RESULT0(str_op_object, str_buf, func, type1) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = str_op_object.func(r, t1, expr_ctx); \
|
|
ASSERT_TRUE(OB_SUCCESS != err); \
|
|
} while(0)
|
|
|
|
|
|
|
|
#define EXPECT_FAIL_RESULT1(str_op_object, str_buf, func, type1, v1) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(v1); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf);\
|
|
int err = str_op_object.func(r, t1, expr_ctx); \
|
|
ASSERT_TRUE(OB_SUCCESS != err); \
|
|
} while(0)
|
|
|
|
#define EXPECT_FAIL_RESULT1_CT(str_op_object, str_buf, func, type1, v1, ct1) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(v1); \
|
|
t1.set_collation_type(ct1); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf);\
|
|
int err = str_op_object.func(r, t1, expr_ctx); \
|
|
ASSERT_TRUE(OB_SUCCESS != err); \
|
|
} while(0)
|
|
|
|
#define EXPECT_RESULT0(str_op_object, str_buf, func, type1, ref_type, ref_value) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(); \
|
|
t1.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
ref.set_##ref_type(); \
|
|
ref.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf);\
|
|
int err = str_op_object.func(r, t1, expr_ctx); \
|
|
_OB_LOG(INFO, "ref=%s r=%s", to_cstring(ref), to_cstring(r)); \
|
|
EXPECT_TRUE(OB_SUCCESS == err); \
|
|
ASSERT_TRUE(ref.get_type() == r.get_type()); \
|
|
if (ref.get_type() != ObNullType) \
|
|
{ \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(ref, r, CS_TYPE_UTF8MB4_BIN, CO_EQ));\
|
|
} \
|
|
} while(0)
|
|
|
|
|
|
|
|
#define EXPECT_RESULT1(str_op_object, str_buf, func, type1, v1, ref_type, ref_value) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(v1); \
|
|
t1.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
ref.set_##ref_type(ref_value); \
|
|
ref.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf);\
|
|
int err = str_op_object.func(r, t1, expr_ctx); \
|
|
_OB_LOG(INFO, "text=%s expect=%s result=%s", to_cstring(t1), to_cstring(ref), to_cstring(r)); \
|
|
EXPECT_TRUE(OB_SUCCESS == err); \
|
|
r.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
ASSERT_TRUE(ref.get_type() == r.get_type()); \
|
|
if (ref.get_type() != ObNullType) \
|
|
{ \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(ref, r, CS_TYPE_UTF8MB4_BIN, CO_EQ));\
|
|
} \
|
|
} while(0)
|
|
|
|
|
|
#define EXPECT_RESULT1_CT(str_op_object, str_buf, func, type1, v1, ct1, ref_type, ref_value, ref_ct) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(v1); \
|
|
t1.set_collation_type(ct1);\
|
|
ref.set_##ref_type(ref_value); \
|
|
ref.set_collation_type(ref_ct);\
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = str_op_object.func(r, t1, expr_ctx); \
|
|
_OB_LOG(INFO, "ref=%s r=%s", to_cstring(ref), to_cstring(r)); \
|
|
EXPECT_TRUE(OB_SUCCESS == err); \
|
|
EXPECT_TRUE(ref.get_type() == r.get_type()); \
|
|
if (ref.get_type() != ObNullType) \
|
|
{ \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(ref, r, ref_ct, CO_EQ));\
|
|
} \
|
|
} while(0)
|
|
|
|
#define EXPECT_FAIL_RESULT2(str_op_object, str_buf, func, type1, v1, type2, v2) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = str_op_object.func(r, t1, t2, expr_ctx); \
|
|
ASSERT_TRUE(OB_SUCCESS != err); \
|
|
} while(0)
|
|
|
|
#define EXPECT_FAIL_RESULT2_CT(str_op_object, str_buf, func, type1, v1, ct1, type2, v2, ct2) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(v1); \
|
|
t1.set_collation_type(ct1); \
|
|
t2.set_##type2(v2); \
|
|
t2.set_collation_type(ct2); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = str_op_object.func(r, t1, t2, expr_ctx); \
|
|
ASSERT_TRUE(OB_SUCCESS != err); \
|
|
} while(0)
|
|
|
|
#define EXPECT_RESULT_WITH_NULL(str_op_object, str_buf, func, type1, type2, v2, ref_type, ref_value) \
|
|
do { \
|
|
UNUSED(ref_value); \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(); \
|
|
t2.set_##type2(v2); \
|
|
ref.set_##ref_type(); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf);\
|
|
int err = str_op_object.func(r, t1, &t2, expr_ctx); \
|
|
_OB_LOG(INFO, "respect=%s result=%s", to_cstring(ref), to_cstring(r)); \
|
|
EXPECT_TRUE(OB_SUCCESS == err); \
|
|
EXPECT_TRUE(ref.get_type() == r.get_type()); \
|
|
EXPECT_TRUE(ref.get_type() == ObNullType); \
|
|
} while(0)
|
|
|
|
|
|
|
|
#define EXPECT_RESULT2(str_op_object, str_buf, func, type1, v1, type2, v2,ref_type, ref_value) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
ref.set_##ref_type(ref_value); \
|
|
ObExprResType res_type; \
|
|
res_type.set_collation_level(CS_LEVEL_EXPLICIT); \
|
|
res_type.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
res_type.set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
str_op_object.set_result_type(res_type); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = str_op_object.func(r, t1, t2, expr_ctx); \
|
|
_OB_LOG(INFO, "ref=%s r=%s, t1=%s, t2=%s", to_cstring(ref), to_cstring(r), to_cstring(t1), to_cstring(t2)); \
|
|
EXPECT_TRUE(OB_SUCCESS == err); \
|
|
EXPECT_TRUE(ref.get_type() == r.get_type()); \
|
|
if (ref.get_type() != ObNullType) \
|
|
{ \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(ref, r, CS_TYPE_UTF8MB4_BIN, CO_EQ)); \
|
|
} \
|
|
} while(0)
|
|
|
|
|
|
|
|
|
|
#define EXPECT_RESULT2_CT(str_op_object, str_buf, func, type1, v1, ct1, type2, v2, ct2, ref_type, ref_value, ref_ct) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(v1); \
|
|
t1.set_collation_type(ct1);\
|
|
t2.set_##type2(v2); \
|
|
t2.set_collation_type(ct2);\
|
|
ref.set_##ref_type(ref_value); \
|
|
ref.set_collation_type(ref_ct);\
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = str_op_object.func(r, t1, t2, expr_ctx); \
|
|
_OB_LOG(INFO, "ref=%s r=%s", to_cstring(ref), to_cstring(r)); \
|
|
EXPECT_TRUE(OB_SUCCESS == err); \
|
|
EXPECT_TRUE(ref.get_type() == r.get_type()); \
|
|
if (ref.get_type() != ObNullType) \
|
|
{ \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(ref, r, ref_ct, CO_EQ));\
|
|
} \
|
|
} while(0)
|
|
|
|
#define EXPECT_FAIL_RESULT3(str_op_object, str_buf, func, type1, v1, type2, v2, type3, v3, ref_type, ref_value) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj t3; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
t3.set_##type3(v3); \
|
|
ref.set_##ref_type(ref_value); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = str_op_object.func(r, t1, t2, t3, expr_ctx); \
|
|
ASSERT_TRUE(OB_SUCCESS != err); \
|
|
} while(0)
|
|
|
|
#define EXPECT_RESULT3(str_op_object, str_buf, func, type1, v1, type2, v2, type3, v3, ref_type, ref_value) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj t3; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
t3.set_##type3(v3); \
|
|
t2.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
t3.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
ref.set_##ref_type(ref_value); \
|
|
ref.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
r.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
ObExprResType res_type; \
|
|
res_type.set_collation_level(CS_LEVEL_EXPLICIT); \
|
|
res_type.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
res_type.set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
str_op_object.set_result_type(res_type); \
|
|
int err = str_op_object.func(r, t1, t2, t3, expr_ctx); \
|
|
_OB_LOG(INFO, "ref=%s r=%s", to_cstring(ref), to_cstring(r)); \
|
|
EXPECT_TRUE(OB_SUCCESS == err); \
|
|
EXPECT_TRUE(ref.get_type() == r.get_type()); \
|
|
r.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
if (ref.get_type() != ObNullType) \
|
|
{ \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(r, ref, CS_TYPE_UTF8MB4_BIN, CO_EQ));\
|
|
} \
|
|
} while(0)
|
|
#define EXPECT_FAIL_RESULT4(str_op_object, str_buf, func, type1, v1, type2, v2, type3, v3, type4, v4, ref_type, ref_value) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj t3; \
|
|
ObObj t4; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
t3.set_##type3(v3); \
|
|
t4.set_##type4(v4); \
|
|
ref.set_##ref_type(ref_value); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = str_op_object.func(r, t1, t2, t3, t4, expr_ctx); \
|
|
ASSERT_TRUE(OB_SUCCESS != err); \
|
|
} while(0)
|
|
|
|
#define EXPECT_RESULT4(str_op_object, str_buf, func, type1, v1, type2, v2, type3, v3, type4, v4, ref_type, ref_value) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj t3; \
|
|
ObObj t4; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
t1.set_##type1(v1); \
|
|
t2.set_##type2(v2); \
|
|
t3.set_##type3(v3); \
|
|
t4.set_##type4(v4); \
|
|
t2.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
t3.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
t4.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
ref.set_##ref_type(ref_value); \
|
|
ref.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
r.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
ObExprResType res_type; \
|
|
res_type.set_collation_level(CS_LEVEL_EXPLICIT); \
|
|
res_type.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
res_type.set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
str_op_object.set_result_type(res_type); \
|
|
int err = str_op_object.func(r, t1, t2, t3, t4, expr_ctx); \
|
|
_OB_LOG(INFO, "ref=%s r=%s", to_cstring(ref), to_cstring(r)); \
|
|
EXPECT_TRUE(OB_SUCCESS == err); \
|
|
EXPECT_TRUE(ref.get_type() == r.get_type()); \
|
|
r.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
if (ref.get_type() != ObNullType) \
|
|
{ \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(r, ref, CS_TYPE_UTF8MB4_BIN, CO_EQ));\
|
|
} \
|
|
} while(0)
|
|
#define EXPECT_RESULTN(obj, str_buf, func, num,ref_type, ref_value,...) \
|
|
{ \
|
|
ObObj params[num]; \
|
|
ObObj ref; \
|
|
ObObj res;\
|
|
LOGIC_GENPARAM##num(params, __VA_ARGS__); \
|
|
ref.set_##ref_type(ref_value);\
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = obj.func(res,params, num, expr_ctx); \
|
|
_OB_LOG(INFO, "ref=%s res=%s ret=%d", to_cstring(ref), to_cstring(res),err); \
|
|
_OB_LOG(INFO, "%ld, %ld", ref.get_data_length(), res.get_data_length()); \
|
|
EXPECT_TRUE(OB_SUCCESS == err); \
|
|
EXPECT_TRUE(ref.get_type() == res.get_type()); \
|
|
if (ref.get_type() != ObNullType) \
|
|
{ \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(res, ref, CS_TYPE_UTF8MB4_BIN, CO_EQ));\
|
|
} \
|
|
} while(0)
|
|
|
|
#define EXPECT_RESULTN_NULL(obj, str_buf, func, num,ref_type, ref_value,...) \
|
|
do { \
|
|
ObObj params[num + 1]; \
|
|
ObObj ref; \
|
|
ObObj res;\
|
|
LOGIC_GENPARAM##num(params, __VA_ARGS__); \
|
|
params[num + 1].set_null();\
|
|
ref.set_##ref_type(ref_value);\
|
|
ref.set_null();\
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = obj.func(res,params, num+1, expr_ctx); \
|
|
_OB_LOG(INFO, "ref=%s res=%s ret=%d", to_cstring(ref), to_cstring(res),err); \
|
|
EXPECT_TRUE(OB_SUCCESS == err); \
|
|
EXPECT_TRUE(ref.get_type() == res.get_type()); \
|
|
if (ref.get_type() != ObNullType) \
|
|
{ \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(res, ref, CS_TYPE_UTF8MB4_BIN, CO_EQ));\
|
|
} \
|
|
} while(0)
|
|
|
|
|
|
#define EXPECT_FAIL_RESULTN(obj, str_buf, func, num,...) \
|
|
do { \
|
|
ObObj params[num]; \
|
|
ObObj res; \
|
|
ObObj ref;\
|
|
LOGIC_GENPARAM##num(params, __VA_ARGS__); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = obj.func(res, params, num, expr_ctx); \
|
|
ASSERT_TRUE(OB_SUCCESS != err); \
|
|
} while(0)
|
|
|
|
#define EXPECT_RESULTN_TO_INNER(obj, str_buf, func, is_null, is_to_str, num,ref_type, ref_value,...) \
|
|
do { \
|
|
ObObj params[num]; \
|
|
ObObj ref; \
|
|
ObObj res;\
|
|
LOGIC_GENPARAM##num(params, __VA_ARGS__); \
|
|
ObArray<ObString> str_values;\
|
|
int ret = OB_SUCCESS;\
|
|
for (int64_t i = 0; OB_SUCCESS == ret && i < num - 2; ++i) \
|
|
{ \
|
|
ObString str;\
|
|
ret = params[i].get_varchar(str); \
|
|
EXPECT_TRUE(OB_SUCCESS == ret); \
|
|
ret = str_values.push_back(str);\
|
|
EXPECT_TRUE(OB_SUCCESS == ret); \
|
|
}\
|
|
ret = obj.shallow_copy_str_values(str_values); \
|
|
EXPECT_TRUE(OB_SUCCESS == ret); \
|
|
ObString refer_string(ref_value);\
|
|
ObEnumSetInnerValue inner_value(params[num-1].get_uint64(), refer_string);\
|
|
char local_buf[1024] = {0};\
|
|
int64_t pos = 0;\
|
|
if (is_null) {\
|
|
params[num-1].set_null();\
|
|
} else if (is_to_str) {\
|
|
ref.set_##ref_type(refer_string);\
|
|
ref.set_collation_type(CS_TYPE_UTF8MB4_BIN);\
|
|
} else {\
|
|
ret = inner_value.serialize(local_buf, 1024, pos);\
|
|
EXPECT_TRUE(OB_SUCCESS == ret); \
|
|
ref.set_##ref_type(local_buf, (ObString::obstr_size_t)pos);\
|
|
ref.set_collation_type(CS_TYPE_UTF8MB4_BIN);\
|
|
}\
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
ret = obj.func(res, params[num - 2], params[num - 1], expr_ctx); \
|
|
EXPECT_TRUE(OB_SUCCESS == ret); \
|
|
ObString ref_string = ref.get_varchar();\
|
|
ObString res_string = res.get_varchar();\
|
|
_OB_LOG(INFO, "%ld, %ld", ref.get_data_length(), res.get_data_length()); \
|
|
_OB_LOG(INFO, "ref: %.*s result: %.*s", ref_string.length(), ref_string.ptr(), res_string.length(), res_string.ptr()); \
|
|
if (true == is_null) {\
|
|
EXPECT_TRUE(ObNullType == res.get_type()); \
|
|
_OB_LOG(INFO, "out_value is NULL" ); \
|
|
} else if (is_to_str){ \
|
|
EXPECT_TRUE(ref.get_type() == res.get_type()); \
|
|
if (ref.get_type() != ObNullType) \
|
|
{ \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(res, ref, CS_TYPE_UTF8MB4_BIN, CO_EQ));\
|
|
}\
|
|
} else {\
|
|
ObEnumSetInnerValue out_value;\
|
|
pos = 0; \
|
|
ret = out_value.deserialize(res_string.ptr(), res_string.length(), pos);\
|
|
_OB_LOG(INFO, "out_value:%s", to_cstring(out_value)); \
|
|
EXPECT_TRUE(OB_SUCCESS == ret); \
|
|
EXPECT_TRUE(ref.get_type() == res.get_type()); \
|
|
EXPECT_TRUE(ref.get_varchar() == res.get_varchar()); \
|
|
if (ref.get_type() != ObNullType) \
|
|
{ \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(res, ref, CS_TYPE_UTF8MB4_BIN, CO_EQ));\
|
|
} \
|
|
}\
|
|
} while(0)
|
|
|
|
|
|
#define EXPECT_RESULT2_UTF8MB4CI(str_op_object, str_buf, func, type1, v1, type2, v2,ref_type, ref_value) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj r; \
|
|
ObObj ref; \
|
|
t1.set_##type1(v1); \
|
|
t1.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);\
|
|
t2.set_##type2(v2); \
|
|
t2.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);\
|
|
ref.set_##ref_type(ref_value); \
|
|
ref.set_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);\
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf); \
|
|
int err = str_op_object.func(r, t1, t2, expr_ctx); \
|
|
_OB_LOG(INFO, "ref=%s r=%s", to_cstring(ref), to_cstring(r)); \
|
|
EXPECT_TRUE(OB_SUCCESS == err); \
|
|
EXPECT_TRUE(ref.get_type() == r.get_type()); \
|
|
if (ref.get_type() != ObNullType) \
|
|
{ \
|
|
EXPECT_TRUE(ObObjCmpFuncs::compare_oper_nullsafe(ref, r, CS_TYPE_UTF8MB4_GENERAL_CI, CO_EQ));\
|
|
} \
|
|
} while(0)
|
|
|
|
|
|
OB_INLINE int64_t trunc_double(const double &v, int64_t p, int64_t d)
|
|
{
|
|
double shift = v;
|
|
int64_t revert = shift > 0 ? 1 : -1;
|
|
shift *= static_cast<double>(revert);
|
|
shift *= pow(static_cast<double>(10), static_cast<double>(p - d - 1));
|
|
return static_cast<int64_t>(shift) * revert;
|
|
}
|
|
|
|
double fabs(double x);
|
|
|
|
OB_INLINE int64_t find_effective_start(double v)
|
|
{
|
|
double d = 0;
|
|
if (fabs(v - 0) < 0.000000000000001) {
|
|
d = 0;
|
|
} else {
|
|
d = floor(log(v) / log(10));
|
|
}
|
|
return static_cast<int64_t>(d);
|
|
}
|
|
|
|
#define DOUBLE_CMP_MAX_P 14
|
|
|
|
OB_INLINE int64_t double_cmp_given_precision(double v1, double v2, int p)
|
|
{
|
|
int64_t d1 = 0;
|
|
int64_t d2 = 0;
|
|
int64_t d = 0;
|
|
int64_t revert = 1;
|
|
int64_t res = 0;
|
|
double temp1 = 0;
|
|
double temp2 = 0;
|
|
int64_t e1 = 0;
|
|
int64_t e2 = 0;
|
|
if (v1 > 0 && v2 < 0)
|
|
res = 1;
|
|
else if (v1 < 0 && v2 > 0)
|
|
res = -1;
|
|
else {
|
|
revert = v1 < 0 ? -1 : 1;
|
|
temp1 = static_cast<double>(revert) * v1;
|
|
temp2 = static_cast<double>(revert) * v2;
|
|
d1 = find_effective_start(temp1);
|
|
d2 = find_effective_start(temp2);
|
|
d = d1 > d2 ? d1 : d2;
|
|
e1 = trunc_double(temp1, p + 1, d); //assure LSBs of EFN are the same,next digit can be different
|
|
e2 = trunc_double(temp2, p + 1, d);
|
|
int64_t delta = 0;
|
|
delta = e1 > e2 ? (e1 - e2) : (e2 - e1);
|
|
if (delta < 10) {
|
|
res = 0;
|
|
} else if (e1 > e2) {
|
|
res = 1;
|
|
} else if (e1 < e2) {
|
|
res = -1;
|
|
}
|
|
res = res * revert;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
#define ARITH_EXPECT_OBJ_DOUBLE(cmp_op, str_buf, func, type1, v1, type2, v2, rv, p) \
|
|
do { \
|
|
ObObj t1; \
|
|
ObObj t2; \
|
|
ObObj vres; \
|
|
cmp_op op(g_alloc_); \
|
|
t1.set_##type1(v1); \
|
|
t1.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
t2.set_##type2(v2); \
|
|
t2.set_collation_type(CS_TYPE_UTF8MB4_BIN); \
|
|
int ret = op.func(vres, t1, t2, str_buf, -1); \
|
|
EXPECT_TRUE(OB_SUCC(ret)); \
|
|
ObObj res; \
|
|
EXPECT_TRUE(vres.is_double()==true); \
|
|
EXPECT_TRUE(double_cmp_given_precision(vres.get_double(),rv,p) == 0);\
|
|
} while(0)
|
|
|
|
#define EXPECT_NULL1(obj, str_buf, func) \
|
|
do { \
|
|
ObObj ob; \
|
|
ObObj res; \
|
|
ob.set_null(); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf);\
|
|
int err = obj.func(res, ob, expr_ctx); \
|
|
EXPECT_TRUE(OB_SUCCESS == err); \
|
|
ASSERT_TRUE(res.get_type() == ObNullType); \
|
|
} while(0)
|
|
|
|
#define EXPECT_BUF_NOT_INIT1(obj, str_buf, func, t1, v1) \
|
|
do { \
|
|
ObObj ob; \
|
|
ObObj res; \
|
|
ob.set_##t1(v1); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, NULL); \
|
|
int err = obj.func(res, ob, expr_ctx); \
|
|
ASSERT_TRUE(OB_NOT_INIT == err); \
|
|
} while(0)
|
|
|
|
#define EXPECT_ALLOCATE_MEMORY_FAILED1(obj, str_buf, func, t1, v1) \
|
|
do { \
|
|
ObObj ob; \
|
|
ObObj res; \
|
|
ob.set_##t1(v1); \
|
|
ObExprCtx expr_ctx(NULL, NULL, NULL, str_buf);\
|
|
int err = obj.func(res, ob, expr_ctx); \
|
|
ASSERT_TRUE(OB_ALLOCATE_MEMORY_FAILED == err);\
|
|
} while(0)
|
|
|
|
inline oceanbase::common::number::ObNumber TO_NMB(const char *str)
|
|
{
|
|
oceanbase::common::number::ObNumber nmb;
|
|
static oceanbase::common::CharArena s_allocator;
|
|
nmb.from(str, s_allocator);
|
|
return nmb;
|
|
}
|
|
|
|
#define FLOAT_MAX 3.40e+38
|
|
#define DOUBLE_MAX 1.79e+308
|
|
|
|
#endif /* _OB_EXPR_TEST_UTILS_H */
|