add DEGREES() function that converts radian to degree.
This commit is contained in:
parent
614d2970e8
commit
75c14d5c88
1
deps/oblib/src/lib/ob_name_def.h
vendored
1
deps/oblib/src/lib/ob_name_def.h
vendored
@ -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 ¶ms,
|
||||
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*/
|
||||
|
86
src/sql/engine/expr/ob_expr_degrees.cpp
Normal file
86
src/sql/engine/expr/ob_expr_degrees.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
// 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
|
30
src/sql/engine/expr/ob_expr_degrees.h
Normal file
30
src/sql/engine/expr/ob_expr_degrees.h
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// 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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user