From 630e4032d863cd18cd5395f2673cac4ce7d2bd0b Mon Sep 17 00:00:00 2001 From: xiaoleizi2016 Date: Tue, 20 Sep 2022 18:32:38 +0800 Subject: [PATCH] fix float or double value directly tested for equality #1041 (#1066) * fix float or double value directly tested for equality * fix problem --- src/sql/engine/expr/ob_expr_div.cpp | 12 +++++++----- src/sql/engine/expr/ob_expr_mod.cpp | 2 +- src/sql/optimizer/ob_opt_est_sel.cpp | 3 ++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/sql/engine/expr/ob_expr_div.cpp b/src/sql/engine/expr/ob_expr_div.cpp index e2ae860b3..30f6593e3 100644 --- a/src/sql/engine/expr/ob_expr_div.cpp +++ b/src/sql/engine/expr/ob_expr_div.cpp @@ -23,6 +23,8 @@ using namespace common; using namespace share; using namespace common::number; +constexpr double EPSILON = 0.000000001; + ObExprDiv::ObExprDiv(ObIAllocator& alloc, ObExprOperatorType type) : ObArithExprOperator(alloc, type, N_DIV, 2, NOT_ROW_DIMENSION, ObExprResultTypeUtil::get_div_result_type, ObExprResultTypeUtil::get_div_calc_type, div_funcs_) @@ -219,7 +221,7 @@ int ObExprDiv::div_float(ObObj& res, const ObObj& left, const ObObj& right, ObIA } else if (OB_UNLIKELY(left.get_type_class() != right.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Invalid types", K(ret), K(left), K(right)); - } else if (fabsf(right.get_float()) == 0.0) { + } else if (fabsf(right.get_float()) < EPSILON) { ret = OB_ERR_DIVISOR_IS_ZERO; LOG_WARN("division by zero not allowed now", K(res), K(left), K(right)); } else { @@ -246,7 +248,7 @@ int ObExprDiv::div_double(ObObj& res, const ObObj& left, const ObObj& right, ObI if (OB_UNLIKELY(left.get_type_class() != right.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Invalid types", K(ret), K(left), K(right)); - } else if (fabs(right.get_double()) == 0.0) { + } else if (fabs(right.get_double()) < EPSILON) { if (is_oracle_mode()) { ret = OB_ERR_DIVISOR_IS_ZERO; LOG_WARN("division by zero not allowed now", K(res), K(left), K(right)); @@ -278,7 +280,7 @@ int ObExprDiv::div_double_no_overflow(ObObj& res, const ObObj& left, const ObObj if (OB_UNLIKELY(left.get_type_class() != right.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Invalid types", K(ret), K(left), K(right)); - } else if (lib::is_mysql_mode() && (fabs(right.get_double()) == 0.0)) { + } else if (lib::is_mysql_mode() && (fabs(right.get_double()) < EPSILON)) { res.set_null(); } else { res.set_double(left.get_double() / right.get_double()); @@ -440,7 +442,7 @@ int ObExprDiv::div_double(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& datum) } else { const double left_d = left->get_double(); const double right_d = right->get_double(); - if (is_mysql_mode() && (fabs(right_d) == 0.0)) { + if (is_mysql_mode() && (fabs(right_d) < EPSILON)) { datum.set_null(); } else { const double result_d = left_d / right_d; @@ -643,7 +645,7 @@ int ObExprDiv::div_float(ObDatum& result, const ObDatum& left, const ObDatum& ri UNUSED(ctx); const float left_f = left.get_float(); const float right_f = right.get_float(); - if (fabsf(right_f) == 0.0) { + if (fabsf(right_f) < EPSILON) { ret = OB_ERR_DIVISOR_IS_ZERO; LOG_WARN("division by zero not allowed now", K(ret), K(right_f)); } else { diff --git a/src/sql/engine/expr/ob_expr_mod.cpp b/src/sql/engine/expr/ob_expr_mod.cpp index 6067f16c6..ef9e259ea 100644 --- a/src/sql/engine/expr/ob_expr_mod.cpp +++ b/src/sql/engine/expr/ob_expr_mod.cpp @@ -214,7 +214,7 @@ int ObExprMod::mod_double(ObObj& res, const ObObj& left, const ObObj& right, ObI if (OB_UNLIKELY(left.get_type_class() != right.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Invalid types", K(ret), K(left), K(right)); - } else if (fabs(right.get_double()) == 0.0) { + } else if (fabs(right.get_double()) < EPSILON) { if (lib::is_oracle_mode()) { res.set_double(left.get_double()); } else { diff --git a/src/sql/optimizer/ob_opt_est_sel.cpp b/src/sql/optimizer/ob_opt_est_sel.cpp index f0a668f53..38152dc90 100644 --- a/src/sql/optimizer/ob_opt_est_sel.cpp +++ b/src/sql/optimizer/ob_opt_est_sel.cpp @@ -35,6 +35,7 @@ using namespace oceanbase::share::schema; namespace oceanbase { namespace sql { double ObOptEstSel::DEFAULT_COLUMN_DISTINCT_RATIO = EST_DEF_COL_NUM_DISTINCT * 1.0 / OB_EST_DEFAULT_ROW_COUNT; +constexpr double EPSILON = 0.000000001; int ObOptEstSel::calculate_selectivity(const ObEstSelInfo& est_sel_info, const ObIArray& quals, double& selectivity, ObIArray* all_predicate_sel, ObJoinType join_type, const ObRelIds* left_rel_ids, @@ -3118,7 +3119,7 @@ int ObOptEstSel::get_agg_sel(const ObEstSelInfo& est_sel_info, const ObRawExpr& } } else if (T_FUN_SUM == aggr_expr->get_expr_type() || T_FUN_AVG == aggr_expr->get_expr_type()) { LOG_TRACE("show group by origen rows and grouped rows", K(origen_rows), K(grouped_rows)); - double rows_per_group = grouped_rows == 0.0 ? origen_rows : origen_rows / grouped_rows; + double rows_per_group = fabs(grouped_rows) < EPSILON ? origen_rows : origen_rows / grouped_rows; if (OB_FAIL(get_agg_sel_with_minmax( est_sel_info, *aggr_expr, const_expr1, const_expr2, type, selectivity, rows_per_group))) { LOG_WARN("failed to get agg sel with minmax", K(ret)); -- GitLab