From cc0e6b8c1289d59d3b18d0f85eb0e726723562cf Mon Sep 17 00:00:00 2001 From: ls0 Date: Wed, 25 Aug 2021 11:09:16 +0800 Subject: [PATCH] implement sql_mode NO_UNSIGNED_SUBTRACTION --- deps/oblib/src/common/object/ob_obj_type.h | 32 +++++++++++++++++++ .../src/common/sql_mode/ob_sql_mode_utils.cpp | 2 +- .../src/common/sql_mode/ob_sql_mode_utils.h | 6 ++++ src/sql/engine/expr/ob_expr_minus.cpp | 11 ++++++- 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/deps/oblib/src/common/object/ob_obj_type.h b/deps/oblib/src/common/object/ob_obj_type.h index 77410e1484..a9a2e2bc75 100644 --- a/deps/oblib/src/common/object/ob_obj_type.h +++ b/deps/oblib/src/common/object/ob_obj_type.h @@ -1228,6 +1228,38 @@ inline bool ob_is_unsigned_type(ObObjType type) ObUDoubleType == type || ObUNumberType == type; } +inline void convert_unsigned_type_to_signed(ObObjType &type) +{ + switch (type) { + case (ObUTinyIntType): + type = ObTinyIntType; + break; + case (ObUSmallIntType): + type = ObSmallIntType; + break; + case (ObUMediumIntType): + type = ObMediumIntType; + break; + case (ObUInt32Type): + type = ObInt32Type; + break; + case (ObUInt64Type): + type = ObIntType; + break; + case (ObUFloatType): + type = ObFloatType; + break; + case (ObUDoubleType): + type = ObDoubleType; + break; + case (ObUNumberType): + type = ObNumberType; + break; + default: + break; + } +} + inline bool ob_is_oracle_numeric_type(ObObjType type) { return ObIntType == type || ob_is_number_tc(type) || ObFloatType == type || ObDoubleType == type; diff --git a/deps/oblib/src/common/sql_mode/ob_sql_mode_utils.cpp b/deps/oblib/src/common/sql_mode/ob_sql_mode_utils.cpp index 78cca32524..181f6a7651 100644 --- a/deps/oblib/src/common/sql_mode/ob_sql_mode_utils.cpp +++ b/deps/oblib/src/common/sql_mode/ob_sql_mode_utils.cpp @@ -60,7 +60,7 @@ ObSqlModeMap SQL_MODE_MAP[] = {{SMO_REAL_AS_FLOAT, STR_REAL_AS_FLOAT}, ObSQLMode SUPPORT_MODE = SMO_STRICT_ALL_TABLES | SMO_STRICT_TRANS_TABLES | SMO_PAD_CHAR_TO_FULL_LENGTH | SMO_ONLY_FULL_GROUP_BY | SMO_NO_AUTO_VALUE_ON_ZERO | SMO_PIPES_AS_CONCAT | - SMO_HIGH_NOT_PRECEDENCE | SMO_ERROR_ON_RESOLVE_CAST; + SMO_HIGH_NOT_PRECEDENCE | SMO_ERROR_ON_RESOLVE_CAST | SMO_NO_UNSIGNED_SUBTRACTION; bool is_sql_mode_supported(ObSQLMode mode) { diff --git a/deps/oblib/src/common/sql_mode/ob_sql_mode_utils.h b/deps/oblib/src/common/sql_mode/ob_sql_mode_utils.h index e2d25fcd52..a26fba0a36 100644 --- a/deps/oblib/src/common/sql_mode/ob_sql_mode_utils.h +++ b/deps/oblib/src/common/sql_mode/ob_sql_mode_utils.h @@ -45,6 +45,12 @@ inline bool is_no_zero_date(ObSQLMode mode) { return (SMO_NO_ZERO_DATE & mode); } + +inline bool is_no_unsigned_subtraction(ObSQLMode mode) +{ + return (SMO_NO_UNSIGNED_SUBTRACTION & mode); +} + inline bool is_mysql_compatible(ObCompatibilityMode mode) { return OCEANBASE_MODE == mode || MYSQL_MODE == mode; diff --git a/src/sql/engine/expr/ob_expr_minus.cpp b/src/sql/engine/expr/ob_expr_minus.cpp index a4e5bcabf7..13be668af1 100644 --- a/src/sql/engine/expr/ob_expr_minus.cpp +++ b/src/sql/engine/expr/ob_expr_minus.cpp @@ -42,8 +42,12 @@ int ObExprMinus::calc_result_type2( static const int64_t CARRY_OFFSET = 1; ObScale scale = SCALE_UNKNOWN_YET; ObPrecision precision = PRECISION_UNKNOWN_YET; + const ObSQLSessionInfo *session = nullptr; bool is_oracle = share::is_oracle_mode(); - if (OB_FAIL(ObArithExprOperator::calc_result_type2(type, type1, type2, type_ctx))) { + if (OB_ISNULL(session = type_ctx.get_session())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to get mysession", K(ret)); + } else if (OB_FAIL(ObArithExprOperator::calc_result_type2(type, type1, type2, type_ctx))) { LOG_WARN("fail to calc result type", K(ret), K(type), K(type1), K(type2)); } else if (is_oracle && type.is_oracle_decimal()) { type.set_scale(ORA_NUMBER_SCALE_UNKNOWN_YET); @@ -78,6 +82,11 @@ int ObExprMinus::calc_result_type2( } else { type.set_precision(precision); } + if (share::is_mysql_mode() && is_no_unsigned_subtraction(session->get_sql_mode())) { + ObObjType convert_type = type.get_type(); + convert_unsigned_type_to_signed(convert_type); + type.set_type(convert_type); + } LOG_DEBUG("calc_result_type2", K(scale), K(type1), K(type2), K(type), K(precision)); } return ret;