Files
oceanbase/unittest/sql/rewrite/test_raw_expr_equal.cpp
zzg19950727 8aff09f2cd [FEAT MERGE]优化器技术改造
Co-authored-by: JinmaoLi <ljm.csmaster@gmail.com>
Co-authored-by: jingtaoye35 <1255153887@qq.com>
Co-authored-by: chimyue <chimyue@gmail.com>
2024-11-19 13:14:40 +00:00

289 lines
9.5 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.
*/
#define USING_LOG_PREFIX SQL
#include <gtest/gtest.h>
#define protected public
#define private public
#include "sql/test_sql_utils.h"
#include "common/object/ob_obj_type.h"
#include "lib/utility/ob_test_util.h"
#include "sql/ob_sql_init.h"
#include "sql/engine/expr/ob_expr_result_type_util.h"
#include "sql/resolver/expr/ob_raw_expr_util.h"
#include "lib/string/ob_sql_string.h"
#undef protected
#undef private
using namespace oceanbase;
using namespace oceanbase::common;
using namespace oceanbase::lib;
using namespace oceanbase::sql;
using namespace oceanbase::share::schema;
const int64_t BUF_LEN = 102400;
class ObRawExprEqualTest: public test::TestSqlUtils, public ::testing::Test
{
public:
ObRawExprEqualTest() {};
virtual ~ObRawExprEqualTest() {};
virtual void SetUp();
virtual void TearDown();
int set_equal_param_exprs(ObOpRawExpr *eq_expr, ObRawExpr *param1, ObRawExpr *param2);
int free_cast_expr(ObOpRawExpr *eq_expr);
};
void ObRawExprEqualTest::SetUp()
{
init();
}
void ObRawExprEqualTest::TearDown()
{
}
int ObRawExprEqualTest::set_equal_param_exprs(ObOpRawExpr *eq_expr, ObRawExpr *param1, ObRawExpr *param2)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(eq_expr) || OB_ISNULL(param1) || OB_ISNULL(param2)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(eq_expr), K(param1), K(param2));
} else if (FALSE_IT(eq_expr->get_param_exprs().reset())) {
// do nothing
} else if (OB_FAIL(eq_expr->set_param_exprs(param1, param2))) {
LOG_WARN("failed to set param exprs", K(ret));
} else if (OB_FAIL(eq_expr->formalize(&session_info_))) {
LOG_WARN("failed to formalize expr", K(ret));
}
return ret;
}
class ObExprResTypeIterator
{
public:
ObExprResTypeIterator();
~ObExprResTypeIterator() {}
int next(ObExprResType &res_type);
private:
int set_res_type(ObExprResType &res_type);
int update_type_idx();
private:
const static int64_t COLLATION_TYPE_COUNT = 8;
const static int64_t DOUBLE_SCALE_COUNT = 4;
const static ObCollationType COLLATION_TYPES[COLLATION_TYPE_COUNT];
const static int64_t DOUBLE_SCALES[DOUBLE_SCALE_COUNT];
private:
ObObjType type_;
int64_t sub_type_idx_;
};
ObExprResTypeIterator::ObExprResTypeIterator()
: type_(ObTinyIntType),
sub_type_idx_(0)
{
}
const ObCollationType ObExprResTypeIterator::COLLATION_TYPES[COLLATION_TYPE_COUNT] = {
CS_TYPE_UTF8MB4_GENERAL_CI,
CS_TYPE_UTF8MB4_BIN,
CS_TYPE_LATIN1_BIN,
CS_TYPE_GBK_CHINESE_CI,
CS_TYPE_GBK_BIN,
CS_TYPE_UTF16_GENERAL_CI,
CS_TYPE_UTF16_BIN,
CS_TYPE_BINARY
};
const int64_t ObExprResTypeIterator::DOUBLE_SCALES[DOUBLE_SCALE_COUNT] = {
SCALE_UNKNOWN_YET,
0,
10,
OB_MAX_DOUBLE_FLOAT_SCALE
};
int ObExprResTypeIterator::next(ObExprResType &res_type)
{
int ret = OB_SUCCESS;
res_type.reset();
if (ObMaxType == type_) {
ret = OB_ITER_END;
} else if (OB_FAIL(set_res_type(res_type))) {
LOG_WARN("failed to set res type", K(ret));
} else if (OB_FAIL(update_type_idx())) {
LOG_WARN("failed to update type idx", K(ret));
}
return ret;
}
int ObExprResTypeIterator::set_res_type(ObExprResType &res_type)
{
int ret = OB_SUCCESS;
res_type.set_type(type_);
res_type.set_precision(ObAccuracy::DDL_DEFAULT_ACCURACY[type_].precision_);
res_type.set_scale(ObAccuracy::DDL_DEFAULT_ACCURACY[type_].scale_);
res_type.set_collation_type(CS_TYPE_BINARY);
res_type.set_collation_level(ObRawExprUtils::get_column_collation_level(type_));
if (ob_is_nstring(type_)) {
res_type.set_collation_type(CS_TYPE_UTF16_BIN);
res_type.set_length(100);
} else if (ob_is_string_or_lob_type(type_)) {
res_type.set_collation_type(COLLATION_TYPES[sub_type_idx_]);
res_type.set_length(100);
} else if (ob_is_double_type(type_)) {
res_type.set_scale(DOUBLE_SCALES[sub_type_idx_]);
}
return ret;
}
int ObExprResTypeIterator::update_type_idx()
{
int ret = OB_SUCCESS;
++sub_type_idx_;
if ((ob_is_string_or_lob_type(type_) && !ob_is_nstring(type_)
&& sub_type_idx_ < 1) ||
(ob_is_double_type(type_) && sub_type_idx_ < 1)) {
// do nothing
} else {
type_ = static_cast<ObObjType>(type_ + 1);
sub_type_idx_ = 0;
}
return ret;
}
TEST_F(ObRawExprEqualTest, equal_compare_func)
{
int ret = OB_SUCCESS;
ObExprResType type1;
ObExprResType type2;
ObExprResTypeIterator iter1;
while (OB_SUCC(ret)) {
ObExprResTypeIterator iter2;
if (OB_FAIL(iter1.next(type1))) {
LOG_WARN("failed to iter type A", K(ret));
break;
}
while (OB_SUCC(ret)) {
if (OB_FAIL(iter2.next(type2))) {
LOG_WARN("failed to iter type B", K(ret));
break;
} else {
bool has_lob_header = type1.has_lob_header() || type2.has_lob_header();
auto func_ptr = ObExprCmpFuncsHelper::get_eval_expr_cmp_func(type1.get_type(),
type2.get_type(),
type1.get_precision(),
type2.get_precision(),
type1.get_scale(),
type2.get_scale(),
CO_EQ,
lib::is_oracle_mode(),
CS_TYPE_BINARY,
has_lob_header);
bool has_cmp_func = NULL != func_ptr;
ObObjType equal_type = ObMaxType;
ASSERT_EQ(OB_SUCCESS, ObExprResultTypeUtil::get_relational_equal_type(
equal_type, type1.get_type(), type2.get_type()));
bool can_deduce_equal = ObMaxType != equal_type;
if (can_deduce_equal && !has_cmp_func) {
EXPECT_EQ(can_deduce_equal, has_cmp_func);
fprintf(stdout, "unexpected cmp func %d %d %d %d %d\n",
type1.get_type(), type1.get_collation_type(),
type2.get_type(), type2.get_collation_type(),
equal_type);
LOG_WARN("unexpected cmp func", K(type1.get_type()), K(type2.get_type()), KP(func_ptr));
}
}
}
if (OB_ITER_END == ret) {
ret = OB_SUCCESS;
}
}
EXPECT_EQ(OB_ITER_END, ret);
}
TEST_F(ObRawExprEqualTest, type_comparable)
{
int ret = OB_SUCCESS;
ObExprResTypeIterator iter1;
ObColumnRefRawExpr *expr1 = NULL;
ObColumnRefRawExpr *expr2 = NULL;
ObOpRawExpr *eq_expr = NULL;
ASSERT_EQ(OB_SUCCESS, expr_factory_.create_raw_expr(T_REF_COLUMN, expr1));
ASSERT_EQ(OB_SUCCESS, expr_factory_.create_raw_expr(T_REF_COLUMN, expr2));
bool can_compare = true;
ObObjType equal_type = ObMaxType;
const ObExprResType &type1 = expr1->get_result_type();
const ObExprResType &type2 = expr2->get_result_type();
while (OB_SUCC(ret)) {
ObExprResTypeIterator iter2;
ObArenaAllocator allocator;
ObRawExprFactory expr_factory(allocator);
ASSERT_EQ(OB_SUCCESS, expr_factory.create_raw_expr(T_OP_EQ, eq_expr));
if (OB_FAIL(iter1.next(expr1->result_type_))) {
LOG_WARN("failed to iter type A", K(ret));
break;
}
while (OB_SUCC(ret))
{
can_compare = true;
if (OB_FAIL(iter2.next(expr2->result_type_))) {
LOG_WARN("failed to iter type B", K(ret));
break;
} else if (OB_FAIL(set_equal_param_exprs(eq_expr, expr1, expr2))) {
LOG_WARN("failed to set equal param exprs", K(ret));
// unable to compare, just continue
ret = OB_SUCCESS;
can_compare = false;
} else if (eq_expr->get_param_expr(0) != expr1 || eq_expr->get_param_expr(1) != expr2) {
can_compare = false;
}
ASSERT_EQ(OB_SUCCESS, ObExprResultTypeUtil::get_relational_equal_type(equal_type,
type1.get_type(), type2.get_type()));
if (!can_compare && ObMaxType != equal_type) {
EXPECT_EQ(ObMaxType, equal_type);
fprintf(stdout, "unexpected equal type %d %d %d %d %d\n",
type1.get_type(), type1.get_collation_type(),
type2.get_type(), type2.get_collation_type(),
equal_type);
LOG_INFO("unexpected equal type", K(can_compare), K(equal_type),
K(type1), K(type2), KPC(eq_expr));
}
}
if (OB_ITER_END == ret) {
ret = OB_SUCCESS;
}
}
EXPECT_EQ(OB_ITER_END, ret);
}
int main(int argc, char **argv)
{
int ret = 0;
system("rm -rf test_raw_expr_equal.log*");
OB_LOGGER.set_file_name("test_raw_expr_equal.log", true);
if(argc >= 2) {
OB_LOGGER.set_log_level(argv[1]);
} else {
OB_LOGGER.set_log_level("INFO");
}
init_sql_factories();
ContextParam param;
param.set_mem_attr(1001, "Transformer", ObCtxIds::WORK_AREA)
.set_page_size(OB_MALLOC_BIG_BLOCK_SIZE);
::testing::InitGoogleTest(&argc,argv);
CREATE_WITH_TEMP_CONTEXT(param) {
ret = RUN_ALL_TESTS();
}
return ret;
}