Files
oceanbase/src/sql/engine/expr/ob_expr_name_const.cpp
2023-04-27 11:11:24 +00:00

156 lines
5.6 KiB
C++

// (C) Copyright 2015-2016 Alibaba Inc. All Rights Reserved.
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// version 2 as published by the Free Software Foundation.
// Version: $Id$
// Authors:
// yebangyu <>
// Normalizer:
// yebangyu <>
// This file is for implementation of func get_user_var
#define USING_LOG_PREFIX SQL_ENG
#include "sql/engine/expr/ob_expr_name_const.h"
namespace oceanbase
{
using namespace common;
namespace sql
{
ObExprNameConst::ObExprNameConst(ObIAllocator &alloc)
: ObFuncExprOperator(alloc, T_FUN_SYS_NAME_CONST, N_NAME_CONST, 2, NOT_VALID_FOR_GENERATED_COL, NOT_ROW_DIMENSION,
false, false)
{
}
ObExprNameConst::~ObExprNameConst()
{
}
int ObExprNameConst::calc_result_type2(ObExprResType &type,
ObExprResType &type1,
ObExprResType &type2,
ObExprTypeCtx &type_ctx) const
{
int ret = OB_SUCCESS;
const ObRawExpr *raw_expr = type_ctx.get_raw_expr();
if (OB_ISNULL(raw_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null", K(ret), K(raw_expr));
} else {
const ObRawExpr *name_expr = raw_expr->get_param_expr(0);
const ObRawExpr *value_expr = raw_expr->get_param_expr(1);
if (OB_ISNULL(name_expr) || OB_ISNULL(value_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null", K(ret), K(name_expr), K(value_expr));
} else if (!name_expr->is_basic_const_expr_mysql() ||
T_QUESTIONMARK == name_expr->get_expr_type()) {
ret = OB_INVALID_ARGUMENT;
LOG_USER_ERROR(OB_INVALID_ARGUMENT, N_NAME_CONST);
LOG_WARN("name is not simple const expr", K(ret), K(*name_expr));
} else if (!value_expr->is_basic_const_expr_mysql()) {
if (T_OP_NEG != value_expr->get_expr_type() && T_FUN_SYS_SET_COLLATION != value_expr->get_expr_type()) {
ret = OB_INVALID_ARGUMENT;
LOG_USER_ERROR(OB_INVALID_ARGUMENT, N_NAME_CONST);
LOG_WARN("value is not simple const expr or collate function", K(ret), K(*value_expr));
} else {
value_expr = value_expr->get_param_expr(0);
if (OB_ISNULL(value_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null", K(ret), K(value_expr));
} else if ((T_FUN_SYS_CAST == value_expr->get_expr_type()) && CM_IS_IMPLICIT_CAST(value_expr->get_extra())) {
//for cases like -'1'
if (OB_ISNULL(value_expr->get_param_expr(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null", K(ret), K(value_expr->get_param_expr(0)));
} else {
value_expr = value_expr->get_param_expr(0);
}
}
}
}
//check value type
if (OB_FAIL(ret)) {
// do nothing
} else if (!value_expr->is_basic_const_expr_mysql()) {
ret = OB_INVALID_ARGUMENT;
LOG_USER_ERROR(OB_INVALID_ARGUMENT, N_NAME_CONST);
LOG_WARN("value is not simple const expr", K(ret), K(*value_expr));
} else {
const ObExprResType &orig_value_type = value_expr->get_result_type();
if (orig_value_type.get_type() >= ObDateTimeType && orig_value_type.get_type() <= ObTimeType) {
ret = OB_INVALID_ARGUMENT;
LOG_USER_ERROR(OB_INVALID_ARGUMENT, N_NAME_CONST);
LOG_WARN("value can't have prefix like TIME, DATE and TIMESTAMP", K(ret), K(orig_value_type));
} else {
// do nothing
}
}
}
if (OB_SUCC(ret)) {
if (ob_is_integer_type(type2.get_type())) {
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_);
} else {
type.assign(type2);
}
}
return ret;
}
int ObExprNameConst::eval_name_const(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res)
{
int ret = OB_SUCCESS;
ObDatum *name_param = NULL;
ObDatum *value_param = NULL;
ObExpr *name_expr = expr.args_[0];
if (OB_FAIL(expr.eval_param_value(ctx, name_param, value_param))) {
LOG_WARN("eval arg failed", K(ret));
} else if (OB_ISNULL(name_param) || OB_ISNULL(value_param) || OB_ISNULL(name_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("name or value is NULL", K(ret), K(name_param), K(value_param));
} else if (name_param->is_null()) {
ObString fun_name(N_NAME_CONST);
ret = OB_ERR_RESERVED_SYNTAX;
LOG_USER_ERROR(OB_ERR_RESERVED_SYNTAX, fun_name.length(), fun_name.ptr());
LOG_WARN("name should not be NULL", K(ret), K(*name_param));
} else {
//check if name < 0 to be compatiable with mysql
common::ObObjType name_type = name_expr->datum_meta_.get_type();
bool is_neg = false;
if (ObFloatType == name_type) {
is_neg = name_param->get_float() < 0;
} else if (ObDoubleType == name_type) {
is_neg = name_param->get_double() < 0;
} else if (name_type >= ObTinyIntType && name_type <= ObIntType) {
is_neg = name_param->get_int() < 0;
} else if (ObNumberType == name_type) {
number::ObNumber name_nmb(name_param->get_number());
is_neg = name_nmb.is_negative();
}
if (is_neg) {
ret = OB_INVALID_ARGUMENT;
LOG_USER_ERROR(OB_INVALID_ARGUMENT, N_NAME_CONST);
LOG_WARN("name is negtive",K(ret),K(name_param));
} else {
res = *value_param;
}
}
return ret;
}
int ObExprNameConst::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
ObExpr &expr) const
{
int ret = OB_SUCCESS;
UNUSED(expr_cg_ctx);
UNUSED(raw_expr);
expr.eval_func_ = eval_name_const;
return ret;
}
} //namespace sql
} //namespace oceanbase