提交 75c14d5c 编写于 作者: M Monk-Liu 提交者: wangzelin.wzl

add DEGREES() function that converts radian to degree.

上级 614d2970
......@@ -117,6 +117,7 @@
#define N_NUM "num"
#define N_SINH "sinh"
#define N_COSH "cosh"
#define N_DEGREES "degrees"
#define N_TANH "tanh"
#define N_RADIANS "radians"
#define N_IS_JOIN "is_join"
......
......@@ -2013,6 +2013,29 @@ static int double_time(
return ret;
}
static int double_year(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class()
|| ObYearTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type",
K(ret), K(in), K(expect_type));
} else {
uint8_t value = 0;
double in_val = in.get_double();
in_val = in_val < 0 ? INT_MIN : in_val + 0.5;
uint64_t intvalue = static_cast<uint64_t>(in_val);
if (CAST_FAIL(ObTimeConverter::int_to_year(intvalue, value))) {
} else {
SET_RES_YEAR(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int double_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
......@@ -2382,6 +2405,10 @@ static int number_year(
if (OB_ISNULL(value)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null pointer", K(ret), K(value));
} else if (in.get_number().is_negative()) {
uint8_t value = 0;
if (CAST_FAIL(ObTimeConverter::int_to_year(INT_MIN, value))) {
}
} else {
ObObj from;
from.set_varchar(value, static_cast<ObString::obstr_size_t>(strlen(value)));
......@@ -5772,7 +5799,7 @@ ObObjCastFunc OB_OBJ_CAST[ObMaxTC][ObMaxTC] = {
double_datetime, /*datetime*/
double_date, /*date*/
double_time, /*time*/
cast_not_support, /*year*/
double_year, /*year*/
double_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
......
......@@ -354,6 +354,8 @@ ob_set_subtarget(ob_sql engine
engine/expr/ob_expr_pi.cpp
engine/expr/ob_expr_pi.h
engine/expr/ob_expr_radians.cpp
engine/expr/ob_expr_degrees.cpp
engine/expr/ob_expr_degrees.h
engine/expr/ob_expr_res_type_map.cpp
engine/expr/ob_expr_result_type_util.cpp
engine/expr/ob_expr_reverse.cpp
......
......@@ -2230,7 +2230,14 @@ CAST_FUNC_NAME(number, year)
if (OB_ISNULL(nmb_buf)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null pointer", K(ret), K(nmb_buf));
} else if (OB_FAIL(common_string_year(expr, ObString(strlen(nmb_buf), nmb_buf), res_datum))) {
} else if (nmb.is_negative()) {
// the year shouldn't accept a negative number, if we use the common_string_year.
// number like -0.4 could be converted to year, which should raise error in mysql
if (OB_FAIL(common_int_year(expr, INT_MIN, res_datum))) {
LOG_WARN("common_int_year failed", K(ret));
}
} else if (OB_FAIL(common_string_year(expr, ObString(strlen(nmb_buf), nmb_buf),
res_datum))) {
LOG_WARN("common_string_year failed", K(ret));
}
}
......@@ -2635,6 +2642,24 @@ CAST_FUNC_NAME(double, time)
return ret;
}
CAST_FUNC_NAME(double, year)
{
EVAL_ARG()
{
// When we insert 999999999999999999999.9(larger than max int) into a year field in mysql
// Mysql raise the same error as we insert 100 into a year field (1264).
// So the cast from double to int won't raise extra error. That's why we directly use
// static_cast here. Mysql will convert the double to nearest int and insert it to the year field.
double in_val = child_res->get_double();
in_val = in_val < 0 ? INT_MIN : in_val + 0.5;
int64_t val_int = static_cast<int64_t>(in_val);
if (OB_FAIL(common_int_year(expr, val_int, res_datum))) {
LOG_WARN("common_int_time failed", K(ret), K(val_int));
}
}
return ret;
}
CAST_FUNC_NAME(double, string)
{
EVAL_ARG()
......@@ -5916,7 +5941,7 @@ ObExpr::EvalFunc OB_DATUM_CAST_ORACLE_IMPLICIT[ObMaxTC][ObMaxTC] = {
cast_inconsistent_types, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
double_year, /*year*/
double_string, /*string*/
cast_not_expected, /*extend*/
cast_not_expected, /*unknown*/
......
// Copyright (c) 2014-2021 Alibaba Inc. All Right Reserved.
// Author:
// liuqifan.lqf@antgroup.com
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/expr/ob_expr_degrees.h"
#include "lib/number/ob_number_v2.h"
#include "sql/engine/expr/ob_expr_util.h"
#include "sql/parser/ob_item_type.h"
#include "sql/session/ob_sql_session_info.h"
#include <cmath>
using namespace oceanbase::common;
using namespace oceanbase::sql;
namespace oceanbase {
namespace sql {
const double ObExprDegrees::degrees_ratio_ = 180.0 / std::acos(-1);
ObExprDegrees::ObExprDegrees(ObIAllocator &alloc)
: ObFuncExprOperator(alloc, T_FUN_SYS_DEGREES, N_DEGREES, 1, NOT_ROW_DIMENSION)
{}
ObExprDegrees::~ObExprDegrees()
{}
int ObExprDegrees::calc_result_type1(ObExprResType &type, ObExprResType &radian, ObExprTypeCtx &type_ctx) const
{
UNUSED(type_ctx);
int ret = OB_SUCCESS;
if (NOT_ROW_DIMENSION != row_dimension_ || ObMaxType == radian.get_type()) {
ret = OB_ERR_INVALID_TYPE_FOR_OP;
} else {
type.set_double();
radian.set_calc_type(ObDoubleType);
ObExprOperator::calc_result_flag1(type, radian);
}
return ret;
}
int ObExprDegrees::calc_result1(ObObj &result, const ObObj &radian_obj, ObExprCtx &expr_ctx) const
{
int ret = OB_SUCCESS;
double val = 0.0;
if (OB_ISNULL(expr_ctx.calc_buf_)) {
ret = OB_NOT_INIT;
LOG_WARN("expr_ctx.calc_buf_ is NULL", K(ret));
} else if (OB_FAIL(radian_obj.get_double(val))) {
LOG_WARN("get double from obj failed in degrees", K(ret), K(radian_obj), K(val));
} else {
result.set_double(val * degrees_ratio_);
}
return ret;
}
int ObExprDegrees::calc_degrees_expr(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum)
{
int ret = OB_SUCCESS;
ObDatum *radian = NULL;
if (OB_FAIL(expr.args_[0]->eval(ctx, radian))) {
LOG_WARN("eval radian arg failed", K(ret), K(expr));
} else if (radian->is_null()) {
res_datum.set_null();
} else {
const double val = radian->get_double();
// cal result;
res_datum.set_double(val * degrees_ratio_);
}
return ret;
}
int ObExprDegrees::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const
{
int ret = OB_SUCCESS;
UNUSED(expr_cg_ctx);
UNUSED(raw_expr);
if (OB_UNLIKELY(1 != rt_expr.arg_cnt_) || (ObDoubleType != rt_expr.args_[0]->datum_meta_.type_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid arg_cnt_ or res type is invalid", K(ret), K(rt_expr));
} else {
rt_expr.eval_func_ = calc_degrees_expr;
}
return ret;
}
} // namespace sql
} // namespace oceanbase
//
// Author:
// liuqifan.lqf@antgroup.com
//
#ifndef OCEANBASE_SQL_ENGINE_EXPR_DEGREES_
#define OCEANBASE_SQL_ENGINE_EXPR_DEGREES_
#include "sql/engine/expr/ob_expr_operator.h"
namespace oceanbase {
namespace sql {
class ObExprDegrees : public ObFuncExprOperator {
public:
explicit ObExprDegrees(common::ObIAllocator &alloc);
virtual ~ObExprDegrees();
virtual int calc_result_type1(ObExprResType &type, ObExprResType &radian, common::ObExprTypeCtx &type_ctx) const;
virtual int calc_result1(common::ObObj &result, const common::ObObj &radian_obj, common::ObExprCtx &expr_ctx) const;
static int calc_degrees_expr(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum);
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override;
private:
const static double degrees_ratio_;
DISALLOW_COPY_AND_ASSIGN(ObExprDegrees);
};
} // namespace sql
} // namespace oceanbase
#endif
......@@ -184,6 +184,7 @@
#include "ob_expr_to_single_byte.h"
#include "ob_expr_to_multi_byte.h"
#include "ob_expr_convert_tz.h"
#include "ob_expr_degrees.h"
namespace oceanbase {
using namespace common;
......@@ -671,7 +672,7 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
NULL, /* 411 */
NULL, /* 412 */
NULL, /* 413 */
NULL, /* 414 */
ObExprDegrees::calc_degrees_expr, /* 414 */
NULL, /* 415 */
NULL, /* 416 */
NULL, /* 417 */
......@@ -717,7 +718,7 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
ObExprInet6Ntoa::calc_inet6_ntoa, /* 457 */
NULL, // ObExprWeightString::eval_weight_string, /* 458 */
ObExprConvertTZ::eval_convert_tz, /* 459 */
ObExprCrc32::calc_crc32_expr, /* 460 */
ObExprCrc32::calc_crc32_expr /* 460 */
};
REG_SER_FUNC_ARRAY(OB_SFA_SQL_EXPR_EVAL, g_expr_eval_functions, ARRAYSIZEOF(g_expr_eval_functions));
......
......@@ -268,6 +268,7 @@
#include "sql/engine/expr/ob_expr_quarter.h"
#include "sql/engine/expr/ob_expr_bit_length.h"
#include "sql/engine/expr/ob_expr_convert_tz.h"
#include "sql/engine/expr/ob_expr_degrees.h"
using namespace oceanbase::common;
namespace oceanbase {
......@@ -677,6 +678,7 @@ void ObExprOperatorFactory::register_expr_operators()
REG_OP(ObExprLastDay);
REG_OP(ObExprTimeFormat);
REG_OP(ObExprTimestamp);
REG_OP(ObExprDegrees);
// register oracle system function
REG_OP_ORCL(ObExprSysConnectByPath);
REG_OP_ORCL(ObExprTimestampNvl);
......
......@@ -426,6 +426,7 @@ typedef enum ObItemType {
T_FUN_SYS_QUARTER = 711,
T_FUN_SYS_BIT_LENGTH = 712,
T_FUN_SYS_PI = 713,
T_FUN_SYS_DEGREES = 715,
T_FUN_SYS_EXPORT_SET = 721,
T_FUN_SYS_INET6NTOA = 722,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册