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 */
 | 
