156 lines
5.6 KiB
C++
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
|