[CP] Support nls_initcap in oracle mode
This commit is contained in:
parent
93d27616e0
commit
4381d4ce17
1
deps/oblib/src/lib/ob_name_def.h
vendored
1
deps/oblib/src/lib/ob_name_def.h
vendored
@ -1060,4 +1060,5 @@
|
||||
#define N_XMLSERIALIZE "xmlserialize"
|
||||
#define N_XMLCAST "xmlcast"
|
||||
#define N_UPDATEXML "updatexml"
|
||||
#define N_NLS_INITCAP "nls_initcap"
|
||||
#endif //OCEANBASE_LIB_OB_NAME_DEF_H_
|
||||
|
@ -331,6 +331,7 @@
|
||||
#include "ob_expr_normal.h"
|
||||
#include "ob_expr_uniform.h"
|
||||
#include "ob_expr_prefix_pattern.h"
|
||||
#include "ob_expr_initcap.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -1018,7 +1019,7 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
|
||||
ObExprRandom::calc_random_expr_const_seed, /* 589 */
|
||||
ObExprRandom::calc_random_expr_nonconst_seed, /* 590 */
|
||||
ObExprRandstr::calc_random_str, /* 591 */
|
||||
NULL, //ObExprNlsInitCap::calc_nls_initcap_expr /* 592 */
|
||||
ObExprNlsInitCap::calc_nls_initcap_expr, /* 592 */
|
||||
ObExprPrefixPattern::eval_prefix_pattern, /* 593 */
|
||||
ObExprSysMakeXML::eval_sys_makexml, /* 594 */
|
||||
ObExprPrivXmlBinary::eval_priv_xml_binary, /* 595 */
|
||||
@ -1147,7 +1148,7 @@ static ObExpr::EvalBatchFunc g_expr_eval_batch_functions[] = {
|
||||
ObExprDecode::eval_decode_batch, /* 108 */
|
||||
ObExprCoalesce::calc_batch_coalesce_expr, /* 109 */
|
||||
ObExprIsNot::calc_batch_is_not_null, /* 110 */
|
||||
NULL, //ObExprNlsInitCap::calc_nls_initcap_batch /* 111 */
|
||||
ObExprNlsInitCap::calc_nls_initcap_batch, /* 111 */
|
||||
ObExprJoinFilter::eval_range_filter_batch, /* 112 */
|
||||
ObExprJoinFilter::eval_in_filter_batch, /* 113 */
|
||||
calc_sqrt_expr_mysql_in_batch, /* 114 */
|
||||
|
@ -26,7 +26,7 @@ namespace sql
|
||||
{
|
||||
|
||||
ObExprInitcap::ObExprInitcap(ObIAllocator &alloc)
|
||||
: ObStringExprOperator(alloc, T_FUN_SYS_INITCAP, N_INITCAP, 1, VALID_FOR_GENERATED_COL)
|
||||
: ObExprInitcapCommon(alloc, T_FUN_SYS_INITCAP, N_INITCAP, 1)
|
||||
{
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ int ObExprInitcap::calc_result_type1(ObExprResType &type,
|
||||
}
|
||||
|
||||
// last_has_first_letter is used to assign has_first_letter at the beginning, and return last state of text
|
||||
int ObExprInitcap::initcap_string(const ObString &text,
|
||||
int ObExprInitcapCommon::initcap_string(const ObString &text,
|
||||
const ObCollationType cs_type,
|
||||
ObIAllocator *allocator,
|
||||
ObString &res_str,
|
||||
@ -226,5 +226,235 @@ int ObExprInitcap::cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ObExprNlsInitCap::ObExprNlsInitCap(ObIAllocator &alloc)
|
||||
: ObExprInitcapCommon(alloc, T_FUN_SYS_NLS_INITCAP, N_NLS_INITCAP, PARAM_NUM_UNKNOWN)
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprNlsInitCap::calc_result_typeN(ObExprResType &type,
|
||||
ObExprResType *texts,
|
||||
int64_t param_num,
|
||||
ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObBasicSessionInfo *session = type_ctx.get_session();
|
||||
if (OB_ISNULL(session)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("session is NULL", K(ret));
|
||||
} else if (param_num <= 0) {
|
||||
ret = OB_ERR_NOT_ENOUGH_ARGS_FOR_FUN;
|
||||
LOG_WARN("nls_initcap require at least one parameter", K(ret), K(param_num));
|
||||
} else if (param_num > 2) {
|
||||
ret = OB_ERR_TOO_MANY_ARGS_FOR_FUN;
|
||||
LOG_WARN("nls_initcap require at most two parameters", K(ret), K(param_num));
|
||||
} else if (OB_ISNULL(texts)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("Invalid argument", K(ret), K(param_num), K(texts));
|
||||
} else {
|
||||
ObSEArray<ObExprResType*, 1, ObNullAllocator> params;
|
||||
CK(OB_NOT_NULL(session));
|
||||
if (OB_FAIL(params.push_back(&texts[0]))) {
|
||||
LOG_WARN("fail to push back param", K(ret));
|
||||
} else if OB_FAIL(aggregate_string_type_and_charset_oracle(*session, params, type, true)) {
|
||||
LOG_WARN("fail to aggregrate string type and charset", K(ret));
|
||||
} else if (ObVarcharType != type.get_type() && ObNVarchar2Type != type.get_type()) {
|
||||
type.set_varchar();
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(deduce_string_param_calc_type_and_charset(*session, type, params))) {
|
||||
LOG_WARN("fail to deduce string param type", K(ret));
|
||||
} else {
|
||||
const ObCharsetInfo * cs_info = NULL;
|
||||
if (OB_ISNULL(cs_info = ObCharset::get_charset(type.get_collation_type()))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("fail to get charset info", K(ret), K(texts[0]));
|
||||
} else {
|
||||
int64_t len = texts[0].get_calc_length();
|
||||
len = len * cs_info->mbmaxlen;
|
||||
type.set_length(len > OB_MAX_ORACLE_VARCHAR_LENGTH ?
|
||||
OB_MAX_ORACLE_VARCHAR_LENGTH : len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNlsInitCap::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);
|
||||
rt_expr.eval_func_ = calc_nls_initcap_expr;
|
||||
if ((1 == rt_expr.arg_cnt_ && rt_expr.args_[0]->is_batch_result())
|
||||
|| (2 == rt_expr.arg_cnt_
|
||||
&& rt_expr.args_[0]->is_batch_result()
|
||||
&& !rt_expr.args_[1]->is_batch_result())) {
|
||||
rt_expr.eval_batch_func_ = calc_nls_initcap_batch;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNlsInitCap::calc_nls_initcap_expr(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObCollationType cs_type = expr.args_[0]->datum_meta_.cs_type_;
|
||||
bool is_null_result = false;
|
||||
int64_t case_multiply = 1;
|
||||
ObDatum *arg_datum = NULL;
|
||||
if (OB_UNLIKELY(expr.arg_cnt_ <= 0 || expr.arg_cnt_ > 2)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected param number", K(ret), K(expr.arg_cnt_));
|
||||
} else if (OB_FAIL(expr.args_[0]->eval(ctx, arg_datum))) {
|
||||
LOG_WARN("eval arg 0 failed", K(ret), K(expr));
|
||||
} else if (arg_datum->is_null()) {
|
||||
res_datum.set_null();
|
||||
is_null_result = true;
|
||||
} else if (expr.arg_cnt_ == 2) {
|
||||
ObDatum *param_datum = NULL;
|
||||
if (OB_ISNULL(expr.args_[1])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("failed to get nls parameter", K(ret));
|
||||
} else if (OB_FAIL(expr.args_[1]->eval(ctx, param_datum))) {
|
||||
LOG_WARN("eval nls parameter failed", K(ret));
|
||||
} else if (param_datum->is_null()) {
|
||||
// Second param_datum is null, set result null as well.
|
||||
res_datum.set_null();
|
||||
is_null_result = true;
|
||||
} else {
|
||||
const ObString &m_param = param_datum->get_string();
|
||||
if (OB_UNLIKELY(!ObExprOperator::is_valid_nls_param(m_param))) {
|
||||
ret = OB_ERR_INVALID_NLS_PARAMETER_STRING;
|
||||
LOG_WARN("invalid nls parameter", K(ret), K(m_param));
|
||||
} else {
|
||||
// Should set cs_type here, but for now, we do nothing
|
||||
// since nls parameter only support BINARY
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && !is_null_result) {
|
||||
const ObCharsetInfo * cs_info = NULL;
|
||||
if (OB_ISNULL(cs_info = ObCharset::get_charset(cs_type))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("fail to get charset info", K(ret), K(cs_type));
|
||||
} else {
|
||||
case_multiply = std::max(cs_info->caseup_multiply, cs_info->casedn_multiply);
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && !is_null_result) {
|
||||
char *res_buf = NULL;
|
||||
if (OB_ISNULL(res_buf = expr.get_str_res_mem(ctx, arg_datum->len_ * case_multiply))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("allocate memory failed", K(ret));
|
||||
} else {
|
||||
ObDataBuffer buf_alloc(res_buf, arg_datum->len_ * case_multiply);
|
||||
ObString res_str;
|
||||
bool last_has_first_letter = false;
|
||||
if (OB_FAIL(initcap_string(arg_datum->get_string(),
|
||||
expr.args_[0]->datum_meta_.cs_type_,
|
||||
&buf_alloc, res_str, last_has_first_letter))) {
|
||||
LOG_WARN("initcap string failed", K(ret), K(arg_datum->get_string()));
|
||||
} else if (0 == res_str.length()) {
|
||||
// nls_initcap is only for oracle mode. set res be null when string length is 0.
|
||||
res_datum.set_null();
|
||||
} else {
|
||||
res_datum.set_string(res_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprNlsInitCap::calc_nls_initcap_batch(const ObExpr &expr, ObEvalCtx &ctx, const ObBitVector &skip, const int64_t batch_size) {
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum *results = expr.locate_batch_datums(ctx);
|
||||
if (OB_ISNULL(results)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("expr results frame is not init", K(ret));
|
||||
} else if (OB_UNLIKELY(expr.arg_cnt_ <= 0 || expr.arg_cnt_ > 2)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected param number", K(ret), K(expr.arg_cnt_));
|
||||
} else {
|
||||
ObBitVector &eval_flags = expr.get_evaluated_flags(ctx);
|
||||
ObDatum *nlsparam_datum = NULL;
|
||||
bool is_result_all_null = false;
|
||||
ObCollationType cs_type = expr.args_[0]->datum_meta_.cs_type_;
|
||||
int64_t case_multiply = 1;
|
||||
ObDatum *datum_array = NULL;
|
||||
if (OB_FAIL(expr.args_[0]->eval_batch(ctx, skip, batch_size))) {
|
||||
LOG_WARN("failed to eval batch result args0", K(ret));
|
||||
} else {
|
||||
datum_array = expr.args_[0]->locate_batch_datums(ctx);
|
||||
}
|
||||
if (2 == expr.arg_cnt_) {
|
||||
if (OB_FAIL(expr.args_[1]->eval(ctx, nlsparam_datum))) {
|
||||
LOG_WARN("eval fmt_datum failed", K(ret));
|
||||
} else if (nlsparam_datum->is_null()) {
|
||||
is_result_all_null = true;
|
||||
} else {
|
||||
const ObString &m_param = nlsparam_datum->get_string();
|
||||
if (OB_UNLIKELY(!ObExprOperator::is_valid_nls_param(m_param))) {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < batch_size; ++i) {
|
||||
if (skip.at(i) || eval_flags.at(i)) {
|
||||
continue;
|
||||
} else if (!datum_array[i].is_null()) {
|
||||
ret = OB_ERR_INVALID_NLS_PARAMETER_STRING;
|
||||
LOG_WARN("invalid nls parameter", K(ret), K(m_param));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
//if the nls_sort param is not valid, return null instead of an error when the param is null
|
||||
is_result_all_null = true;
|
||||
}
|
||||
} else {
|
||||
// Should set cs_type here, but for now, we do nothing
|
||||
// since nls parameter only support BINARY=
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && !is_result_all_null) {
|
||||
const ObCharsetInfo * cs_info = NULL;
|
||||
if (OB_ISNULL(cs_info = ObCharset::get_charset(cs_type))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("fail to get charset info", K(ret), K(cs_type));
|
||||
} else {
|
||||
case_multiply = std::max(cs_info->caseup_multiply, cs_info->casedn_multiply);
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < batch_size; ++i) {
|
||||
char *res_buf = NULL;
|
||||
if (skip.at(i) || eval_flags.at(i)) {
|
||||
continue;
|
||||
} else if (is_result_all_null || datum_array[i].is_null()) {
|
||||
results[i].set_null();
|
||||
eval_flags.set(i);
|
||||
} else if (OB_ISNULL(res_buf = expr.get_str_res_mem(ctx, datum_array[i].len_ * case_multiply, i))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("allocate memory failed", K(ret));
|
||||
} else {
|
||||
ObDataBuffer buf_alloc(res_buf, datum_array[i].len_ * case_multiply);
|
||||
ObString res_str;
|
||||
bool last_has_first_letter = false;
|
||||
if (OB_FAIL(initcap_string(datum_array[i].get_string(),
|
||||
cs_type,
|
||||
&buf_alloc, res_str, last_has_first_letter))) {
|
||||
LOG_WARN("initcap string failed", K(ret), K(datum_array[i].get_string()));
|
||||
} else if (0 == res_str.length()) {
|
||||
// nls_initcap is only for oracle mode. set res be null when string length is 0.
|
||||
results[i].set_null();
|
||||
eval_flags.set(i);
|
||||
} else {
|
||||
results[i].set_string(res_str);
|
||||
eval_flags.set(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} /* sql */
|
||||
} /* oceanbase */
|
||||
|
@ -19,8 +19,24 @@ namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObExprInitcapCommon : public ObStringExprOperator
|
||||
{
|
||||
public:
|
||||
ObExprInitcapCommon(common::ObIAllocator &alloc,
|
||||
ObExprOperatorType type, const char *name, int32_t param_num)
|
||||
:ObStringExprOperator(alloc, type, name, param_num, VALID_FOR_GENERATED_COL)
|
||||
{}
|
||||
virtual ~ObExprInitcapCommon() {}
|
||||
static int initcap_string(const common::ObString &text,
|
||||
const common::ObCollationType cs_type,
|
||||
common::ObIAllocator *allocator,
|
||||
common::ObString &res_str,
|
||||
bool &has_first_letter);
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprInitcapCommon);
|
||||
};
|
||||
|
||||
class ObExprInitcap : public ObStringExprOperator
|
||||
class ObExprInitcap : public ObExprInitcapCommon
|
||||
{
|
||||
public:
|
||||
explicit ObExprInitcap(common::ObIAllocator &alloc);
|
||||
@ -30,15 +46,34 @@ public:
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int initcap_string(const common::ObString &text,
|
||||
const common::ObCollationType cs_type,
|
||||
common::ObIAllocator *allocator,
|
||||
common::ObString &res_str,
|
||||
bool &has_first_letter);
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprInitcap);
|
||||
};
|
||||
|
||||
class ObExprNlsInitCap : public ObExprInitcapCommon
|
||||
{
|
||||
public:
|
||||
explicit ObExprNlsInitCap(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprNlsInitCap() {}
|
||||
virtual int calc_result_typeN(ObExprResType &type,
|
||||
ObExprResType *texts,
|
||||
int64_t param_num,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int calc_nls_initcap_expr(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
ObDatum &expr_datum);
|
||||
static int calc_nls_initcap_batch(const ObExpr &expr,
|
||||
ObEvalCtx &ctx,
|
||||
const ObBitVector &skip,
|
||||
const int64_t batch_size);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprNlsInitCap);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* OCEANBASE_SQL_ENGINE_EXPR_INITCAP_ */
|
||||
|
@ -1067,6 +1067,7 @@ void ObExprOperatorFactory::register_expr_operators()
|
||||
REG_OP_ORCL(ObExprAtLocal);
|
||||
REG_OP_ORCL(ObExprTimestampToScn);
|
||||
REG_OP_ORCL(ObExprScnToTimestamp);
|
||||
REG_OP_ORCL(ObExprNlsInitCap);
|
||||
//部分内部使用的表达式
|
||||
REG_OP_ORCL(ObExprAdd);
|
||||
REG_OP_ORCL(ObExprAggAdd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user