patch 4.0
This commit is contained in:
@ -17,20 +17,25 @@
|
||||
#include "sql/engine/expr/ob_expr_result_type_util.h"
|
||||
#include "sql/session/ob_sql_session_info.h"
|
||||
|
||||
namespace oceanbase {
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql {
|
||||
namespace sql
|
||||
{
|
||||
|
||||
ObExprArgCase::ObExprArgCase(ObIAllocator& alloc)
|
||||
: ObExprOperator(alloc, T_OP_ARG_CASE, N_ARG_CASE, MORE_THAN_ONE, NOT_ROW_DIMENSION), need_cast_(true)
|
||||
ObExprArgCase::ObExprArgCase(ObIAllocator &alloc)
|
||||
: ObExprOperator(alloc, T_OP_ARG_CASE,
|
||||
N_ARG_CASE, MORE_THAN_ONE, NOT_ROW_DIMENSION,
|
||||
INTERNAL_IN_MYSQL_MODE, INTERNAL_IN_ORACLE_MODE), need_cast_(true)
|
||||
{
|
||||
disable_operand_auto_cast();
|
||||
}
|
||||
|
||||
ObExprArgCase::~ObExprArgCase()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprArgCase::deserialize(const char* buf, const int64_t data_len, int64_t& pos)
|
||||
int ObExprArgCase::deserialize(const char *buf, const int64_t data_len, int64_t &pos)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
need_cast_ = true;
|
||||
@ -53,7 +58,7 @@ int ObExprArgCase::deserialize(const char* buf, const int64_t data_len, int64_t&
|
||||
if (all_are_numeric && (!ob_is_accurate_numeric_type(type))) {
|
||||
all_are_numeric = false;
|
||||
}
|
||||
} // end for
|
||||
}//end for
|
||||
if (OB_SUCC(ret)) {
|
||||
need_cast_ = !(all_same_type || all_are_numeric);
|
||||
}
|
||||
@ -62,10 +67,10 @@ int ObExprArgCase::deserialize(const char* buf, const int64_t data_len, int64_t&
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprArgCase::assign(const ObExprOperator& other)
|
||||
int ObExprArgCase::assign(const ObExprOperator &other)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObExprArgCase* tmp_other = dynamic_cast<const ObExprArgCase*>(&other);
|
||||
const ObExprArgCase *tmp_other = dynamic_cast<const ObExprArgCase *>(&other);
|
||||
if (OB_UNLIKELY(NULL == tmp_other)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid argument. wrong type for other", K(ret), K(other));
|
||||
@ -79,8 +84,15 @@ int ObExprArgCase::assign(const ObExprOperator& other)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprArgCase::calc_result_typeN(
|
||||
ObExprResType& type, ObExprResType* types_stack, int64_t param_num, ObExprTypeCtx& type_ctx) const
|
||||
|
||||
/*
|
||||
* TODO: 这里没有计算compare type,可能导致结果和MySQL不兼容
|
||||
* 目前做法是在calc_result中动态比较, 是否和MySQL行为一致?
|
||||
*/
|
||||
int ObExprArgCase::calc_result_typeN(ObExprResType &type,
|
||||
ObExprResType *types_stack,
|
||||
int64_t param_num,
|
||||
ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
// mysql> drop table t1; create table t1(a date, b int);
|
||||
// mysql> insert into t1 values (20160622, 20160622);
|
||||
@ -94,6 +106,7 @@ int ObExprArgCase::calc_result_typeN(
|
||||
// cmp type of '160622' VS a(date 2016-06-22) is date (or maybe datetime), equal.
|
||||
// so we need a cmp type array, not a single cmp type.
|
||||
|
||||
|
||||
// case c1
|
||||
// when 10 then expr1
|
||||
// when 11 then expr2
|
||||
@ -104,10 +117,10 @@ int ObExprArgCase::calc_result_typeN(
|
||||
if (OB_ISNULL(types_stack)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("null types", K(ret));
|
||||
} else if (OB_UNLIKELY(param_num < 3 || param_num % 2 != 0)) { // an implicit 'else expr' element is added by caller
|
||||
} else if (OB_UNLIKELY(param_num < 3 || param_num % 2 != 0)) { // an implicit 'else expr' element is added by caller
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("param_num is not correct", K(param_num));
|
||||
} else { // param_num >= 4 and param_num is even
|
||||
} else { // param_num >= 4 and param_num is even
|
||||
|
||||
/* take "case c1 when x1 then y1 when x2 then y2 else y3" as an example
|
||||
After studying the behavior of mysql,
|
||||
@ -117,24 +130,28 @@ int ObExprArgCase::calc_result_typeN(
|
||||
int64_t cond_type_count = param_num / 2;
|
||||
int64_t val_type_count = param_num / 2;
|
||||
ObExprResType tmp_res_type;
|
||||
const ObLengthSemantics default_length_semantics =
|
||||
(OB_NOT_NULL(type_ctx.get_session()) ? type_ctx.get_session()->get_actual_nls_length_semantics() : LS_BYTE);
|
||||
if (OB_FAIL(aggregate_result_type_for_case(tmp_res_type,
|
||||
types_stack,
|
||||
cond_type_count,
|
||||
type_ctx.get_coll_type(),
|
||||
lib::is_oracle_mode(),
|
||||
default_length_semantics,
|
||||
type_ctx.get_session(),
|
||||
FALSE))) {
|
||||
const ObLengthSemantics default_length_semantics = (OB_NOT_NULL(type_ctx.get_session()) ? type_ctx.get_session()->get_actual_nls_length_semantics() : LS_BYTE);
|
||||
if (OB_FAIL(aggregate_result_type_for_case(
|
||||
tmp_res_type,
|
||||
types_stack,
|
||||
cond_type_count,
|
||||
type_ctx.get_coll_type(),
|
||||
lib::is_oracle_mode(),
|
||||
default_length_semantics,
|
||||
type_ctx.get_session(),
|
||||
FALSE, FALSE,
|
||||
is_called_in_sql_))) {
|
||||
LOG_WARN("failed to get result type for cmp", K(ret));
|
||||
} else if (OB_FAIL(aggregate_result_type_for_case(type,
|
||||
types_stack + cond_type_count,
|
||||
val_type_count,
|
||||
type_ctx.get_coll_type(),
|
||||
lib::is_oracle_mode(),
|
||||
default_length_semantics,
|
||||
type_ctx.get_session()))) {
|
||||
} else if (OB_FAIL(aggregate_result_type_for_case(
|
||||
type,
|
||||
types_stack + cond_type_count,
|
||||
val_type_count,
|
||||
type_ctx.get_coll_type(),
|
||||
lib::is_oracle_mode(),
|
||||
default_length_semantics,
|
||||
type_ctx.get_session(),
|
||||
true, false,
|
||||
is_called_in_sql_))) {
|
||||
LOG_WARN("failed to get result type", K(ret));
|
||||
} else {
|
||||
// cmp type will be computed dynamically
|
||||
@ -144,8 +161,9 @@ int ObExprArgCase::calc_result_typeN(
|
||||
for (int64_t i = 1; OB_SUCC(ret) && i < cond_type_count; ++i) {
|
||||
ObObjType calc_type;
|
||||
if (ob_is_enumset_tc(types_stack[i].get_type())) {
|
||||
if (OB_FAIL(ObExprResultTypeUtil::get_relational_cmp_type(
|
||||
calc_type, types_stack[0].get_type(), types_stack[i].get_type()))) {
|
||||
if (OB_FAIL(ObExprResultTypeUtil::get_relational_cmp_type(calc_type,
|
||||
types_stack[0].get_type(),
|
||||
types_stack[i].get_type()))) {
|
||||
LOG_WARN("failed to get_cmp_type", K(types_stack[0]), K(types_stack[i]), K(ret));
|
||||
} else {
|
||||
types_stack[i].set_calc_type(calc_type);
|
||||
@ -157,22 +175,13 @@ int ObExprArgCase::calc_result_typeN(
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprArgCase::calc_resultN(ObObj& result, const ObObj* objs_stack, int64_t param_num, ObExprCtx& expr_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
EXPR_DEFINE_CAST_CTX(expr_ctx, CM_NONE);
|
||||
ObCompareCtx cmp_ctx(
|
||||
ObMaxType, result_type_.get_calc_collation_type(), false, expr_ctx.tz_offset_, default_null_pos());
|
||||
if (OB_UNLIKELY(need_cast_)) {
|
||||
ret = calc_with_cast(result, objs_stack, param_num, cmp_ctx, cast_ctx, result_type_, ObExprArgCase::get_cmp_type);
|
||||
} else {
|
||||
ret = calc_without_cast(result, objs_stack, param_num, cast_ctx, cmp_ctx, result_type_);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprArgCase::calc_with_cast(ObObj& result, const ObObj* objs_stack, int64_t param_num, ObCompareCtx& cmp_ctx,
|
||||
ObCastCtx& cast_ctx, const ObExprResType& res_type, const ob_get_cmp_type_func get_cmp_type_func)
|
||||
int ObExprArgCase::calc_with_cast(ObObj &result,
|
||||
const ObObj *objs_stack,
|
||||
int64_t param_num,
|
||||
ObCompareCtx &cmp_ctx,
|
||||
ObCastCtx &cast_ctx,
|
||||
const ObExprResType &res_type,
|
||||
const ob_get_cmp_type_func get_cmp_type_func)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool match_when = false;
|
||||
@ -181,7 +190,7 @@ int ObExprArgCase::calc_with_cast(ObObj& result, const ObObj* objs_stack, int64_
|
||||
if (OB_ISNULL(objs_stack) || OB_ISNULL(get_cmp_type_func)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("stack or get_cmp_type_func is null", K(objs_stack), K(get_cmp_type_func));
|
||||
} else if (OB_UNLIKELY(param_num < 2)) {
|
||||
} else if (OB_UNLIKELY(param_num < 2) ) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param_num", K(param_num));
|
||||
} else {
|
||||
@ -198,15 +207,17 @@ int ObExprArgCase::calc_with_cast(ObObj& result, const ObObj* objs_stack, int64_
|
||||
const bool has_else = (param_num % 2 == 0);
|
||||
int64_t loop = (has_else) ? param_num - 2 : param_num;
|
||||
for (int64_t i = 1; OB_SUCC(ret) && i < loop; i += 2) {
|
||||
if (OB_FAIL(get_cmp_type_func(
|
||||
cmp_ctx.cmp_type_, objs_stack[0].get_type(), objs_stack[i].get_type(), res_type.get_calc_type()))) {
|
||||
if (OB_FAIL(get_cmp_type_func(cmp_ctx.cmp_type_,
|
||||
objs_stack[0].get_type(),
|
||||
objs_stack[i].get_type(),
|
||||
res_type.get_calc_type()))) {
|
||||
LOG_WARN("Get cmp type failed", K(ret));
|
||||
} else {
|
||||
cast_ctx.dest_collation_ = cmp_ctx.cmp_cs_type_;
|
||||
ret = ObExprEqual::calc_cast(equal_result, objs_stack[0], objs_stack[i], cmp_ctx, cast_ctx);
|
||||
if (OB_SUCC(ret)) {
|
||||
if (ObNullType == equal_result.get_type()) {
|
||||
} else if (OB_UNLIKELY(ObInt32Type != equal_result.get_type())) { // ObExprEqual::calc returns int32
|
||||
} else if (OB_UNLIKELY(ObInt32Type != equal_result.get_type())) { // ObExprEqual::calc returns int32
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected calc result type. must be tiny", K(equal_result));
|
||||
} else if (equal_result.is_true()) {
|
||||
@ -221,7 +232,7 @@ int ObExprArgCase::calc_with_cast(ObObj& result, const ObObj* objs_stack, int64_
|
||||
if (!match_when) {
|
||||
if (param_num % 2 == 0) {
|
||||
LOG_DEBUG("match else wrong", K(param_num));
|
||||
tmp_result = objs_stack[param_num - 1]; // match else (default value)
|
||||
tmp_result = objs_stack[param_num - 1]; // match else (default value)
|
||||
} else {
|
||||
tmp_result.set_null();
|
||||
}
|
||||
@ -233,8 +244,12 @@ int ObExprArgCase::calc_with_cast(ObObj& result, const ObObj* objs_stack, int64_
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprArgCase::calc_without_cast(ObObj& result, const ObObj* objs_stack, int64_t param_num, ObCastCtx& cast_ctx,
|
||||
ObCompareCtx& cmp_ctx, const ObExprResType& res_type)
|
||||
int ObExprArgCase::calc_without_cast(ObObj &result,
|
||||
const ObObj *objs_stack,
|
||||
int64_t param_num,
|
||||
ObCastCtx &cast_ctx,
|
||||
ObCompareCtx &cmp_ctx,
|
||||
const ObExprResType &res_type)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool match_when = false;
|
||||
@ -244,7 +259,7 @@ int ObExprArgCase::calc_without_cast(ObObj& result, const ObObj* objs_stack, int
|
||||
if (OB_ISNULL(objs_stack)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("stack is null", K(objs_stack), K(ret));
|
||||
} else if (OB_UNLIKELY(param_num < 2)) {
|
||||
} else if (OB_UNLIKELY(param_num < 2) ) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param_num", K(param_num));
|
||||
} else {
|
||||
@ -270,7 +285,7 @@ int ObExprArgCase::calc_without_cast(ObObj& result, const ObObj* objs_stack, int
|
||||
LOG_WARN("unexpected error. cast should not be necessary", K(objs_stack[0]), K(objs_stack[i]), K(ret));
|
||||
} else {
|
||||
if (ObNullType == equal_result.get_type()) {
|
||||
} else if (OB_UNLIKELY(ObInt32Type != equal_result.get_type())) { // ObExprEqual::calc returns int32 result
|
||||
} else if (OB_UNLIKELY(ObInt32Type != equal_result.get_type())) { // ObExprEqual::calc returns int32 result
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected calc result type. must be tiny", K(equal_result));
|
||||
} else if (equal_result.is_true()) {
|
||||
@ -279,29 +294,28 @@ int ObExprArgCase::calc_without_cast(ObObj& result, const ObObj* objs_stack, int
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // end for
|
||||
}//end for
|
||||
if (OB_SUCC(ret)) {
|
||||
if (!match_when) {
|
||||
if (param_num % 2 == 0) {
|
||||
LOG_DEBUG("match else wrong", K(param_num));
|
||||
tmp_result = objs_stack[param_num - 1]; // match else (default value)
|
||||
tmp_result = objs_stack[param_num - 1]; // match else (default value)
|
||||
} else {
|
||||
tmp_result.set_null();
|
||||
}
|
||||
}
|
||||
cast_ctx.dest_collation_ = res_type.get_collation_type();
|
||||
ret = ObObjCaster::to_type(res_type.get_type(), res_type.get_collation_type(), cast_ctx, tmp_result, result);
|
||||
} // end ob_succ(ret)
|
||||
}//end ob_succ(ret)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprArgCase::cg_expr(ObExprCGCtx&, const ObRawExpr&, ObExpr&) const
|
||||
int ObExprArgCase::cg_expr(ObExprCGCtx &, const ObRawExpr &, ObExpr &) const
|
||||
{
|
||||
int ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("this expr should be rewrote in new engine", K(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user