support last_day in mysql mode
This commit is contained in:
@ -45,6 +45,28 @@ int ObExprPeriodDiff::calc_result2(ObObj& result, const ObObj& left, const ObObj
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_year_month(const uint64_t value, uint64_t &year, uint64_t &month)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const uint64_t YEAR_BASE_YEAR = 1900;
|
||||
const uint64_t YEAR_VALUE_FACTOR = 100;
|
||||
const uint64_t YEAR_ADJUST_THRESHOLD = 70;
|
||||
const uint64_t YEAR_ADJUST_OFFSET = 2000;
|
||||
year = value / YEAR_VALUE_FACTOR;
|
||||
uint64_t tmp = year;
|
||||
/*
|
||||
*11(uint) will be treat as 11 + YEAR_ADJUST_OFFSET = 2011(year)
|
||||
*68(uint) will be treat as 68 + YEAR_BASE_YEAR = 1968(year)
|
||||
*1234(uint) will be treat as 1234(year)
|
||||
*/
|
||||
if (year < YEAR_ADJUST_THRESHOLD)
|
||||
year += YEAR_ADJUST_OFFSET;
|
||||
else if (tmp < YEAR_VALUE_FACTOR)
|
||||
year += YEAR_BASE_YEAR;
|
||||
month = value - tmp * YEAR_VALUE_FACTOR; // % operation ? too expensive !
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int ObExprPeriodDiff::calc(T& result, const T& left, const T& right)
|
||||
{
|
||||
@ -67,28 +89,6 @@ int ObExprPeriodDiff::calc(T& result, const T& left, const T& right)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprPeriodDiff::get_year_month(const uint64_t value, uint64_t& year, uint64_t& month)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const uint64_t YEAR_BASE_YEAR = 1900;
|
||||
const uint64_t YEAR_VALUE_FACTOR = 100;
|
||||
const uint64_t YEAR_ADJUST_THRESHOLD = 70;
|
||||
const uint64_t YEAR_ADJUST_OFFSET = 2000;
|
||||
year = value / YEAR_VALUE_FACTOR;
|
||||
uint64_t tmp = year;
|
||||
/*
|
||||
*11(uint) will be treat as 11 + YEAR_ADJUST_OFFSET = 2011(year)
|
||||
*68(uint) will be treat as 68 + YEAR_BASE_YEAR = 1968(year)
|
||||
*1234(uint) will be treat as 1234(year)
|
||||
*/
|
||||
if (year < YEAR_ADJUST_THRESHOLD)
|
||||
year += YEAR_ADJUST_OFFSET;
|
||||
else if (tmp < YEAR_VALUE_FACTOR)
|
||||
year += YEAR_BASE_YEAR;
|
||||
month = value - tmp * YEAR_VALUE_FACTOR; // % operation ? too expensive !
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprPeriodDiff::cg_expr(ObExprCGCtx& op_cg_ctx, const ObRawExpr& raw_expr, ObExpr& rt_expr) const
|
||||
{
|
||||
UNUSED(op_cg_ctx);
|
||||
@ -124,5 +124,119 @@ int ObExprPeriodDiff::calc_perioddiff(const ObExpr& expr, ObEvalCtx& ctx, ObDatu
|
||||
return ret;
|
||||
}
|
||||
|
||||
ObExprPeriodAdd::ObExprPeriodAdd(ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_PERIOD_ADD, N_PERIOD_ADD, 2, NOT_ROW_DIMENSION)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprPeriodAdd::~ObExprPeriodAdd()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprPeriodAdd::calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &left,
|
||||
ObExprResType &right,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
type.set_int();
|
||||
type.set_scale(common::ObAccuracy::DDL_DEFAULT_ACCURACY[common::ObIntType].scale_);
|
||||
type.set_precision(common::ObAccuracy::DDL_DEFAULT_ACCURACY[common::ObIntType].precision_);
|
||||
left.set_calc_type(common::ObIntType);
|
||||
right.set_calc_type(common::ObIntType);
|
||||
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_STRING_INTEGER_TRUNC);
|
||||
return common::OB_SUCCESS;
|
||||
}
|
||||
|
||||
int ObExprPeriodAdd::calc_result2(ObObj &result,
|
||||
const ObObj &left,
|
||||
const ObObj &right,
|
||||
ObExprCtx &expr_ctx) const
|
||||
{
|
||||
UNUSED(expr_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(left.is_null() || right.is_null())) {
|
||||
result.set_null();
|
||||
} else {
|
||||
TYPE_CHECK(left, ObIntType);
|
||||
TYPE_CHECK(right, ObIntType);
|
||||
if (OB_SUCC(ret)) {
|
||||
ret = calc(result, left, right);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int ObExprPeriodAdd::calc(
|
||||
T &result,
|
||||
const T &left,
|
||||
const T &right)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t lvalue = left.get_int();
|
||||
int64_t rvalue = right.get_int();
|
||||
uint64_t lyear = 0;
|
||||
uint64_t lmonth = 0;
|
||||
if (OB_UNLIKELY(lvalue <= 0)) {
|
||||
// not consistent with Mysql, by design.
|
||||
result.set_int(0);
|
||||
} else if (OB_FAIL(get_year_month(static_cast<uint64_t>(lvalue), lyear, lmonth))) {
|
||||
LOG_WARN("get_year_month failed", K(ret), K(lvalue), K(lyear), K(lmonth));
|
||||
} else {
|
||||
int64_t res_months = lyear * MONS_PER_YEAR + lmonth + rvalue;
|
||||
int64_t year = (res_months - 1) / MONS_PER_YEAR;
|
||||
int64_t month = ((res_months - 1) % MONS_PER_YEAR) + 1;
|
||||
if (OB_UNLIKELY(res_months <= 0 )) {
|
||||
result.set_int(0);
|
||||
} else {
|
||||
if (year < 70) {
|
||||
year += 2000;
|
||||
} else if (year < 100) {
|
||||
year += 1900;
|
||||
}
|
||||
result.set_int(year * 100 + month);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprPeriodAdd::cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
UNUSED(op_cg_ctx);
|
||||
UNUSED(raw_expr);
|
||||
int ret = OB_SUCCESS;
|
||||
if (rt_expr.arg_cnt_ != 2) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("periodadd expr should have two params", K(ret), K(rt_expr.arg_cnt_));
|
||||
} else if (OB_ISNULL(rt_expr.args_) || OB_ISNULL(rt_expr.args_[0])
|
||||
|| OB_ISNULL(rt_expr.args_[1])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("children of periodadd expr is null", K(ret), K(rt_expr.args_));
|
||||
} else {
|
||||
CK(ObIntType == rt_expr.args_[0]->datum_meta_.type_);
|
||||
CK(ObIntType == rt_expr.args_[1]->datum_meta_.type_);
|
||||
rt_expr.eval_func_ = ObExprPeriodAdd::calc_periodadd;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprPeriodAdd::calc_periodadd(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum *param_datum1 = NULL;
|
||||
ObDatum *param_datum2 = NULL;
|
||||
if (OB_FAIL(expr.eval_param_value(ctx, param_datum1, param_datum2))) {
|
||||
LOG_WARN("eval param value failed", K(ret));
|
||||
} else if (OB_UNLIKELY(param_datum1->is_null() || param_datum2->is_null())) {
|
||||
expr_datum.set_null();
|
||||
} else {
|
||||
ObDatum *res_datum = static_cast<ObDatum *>(&expr_datum);
|
||||
ret = calc(*res_datum, *param_datum1, *param_datum2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
} // namespace oceanbase
|
||||
Reference in New Issue
Block a user