expr repeat/space/lrpad opt for text type

This commit is contained in:
skylhd
2023-06-13 02:12:20 +00:00
committed by ob-robot
parent 48544979bf
commit 05295dd0f6
7 changed files with 149 additions and 36 deletions

View File

@ -198,11 +198,35 @@ int ObExprBaseLRpad::calc_type_length_oracle(const ObExprResType &result_type,
return ret;
}
int ObExprBaseLRpad::get_origin_len_obj(ObObj &len_obj) const
{
int ret = OB_SUCCESS;
ObRawExpr *expr = NULL;
if (OB_ISNULL(expr = get_raw_expr())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to get_raw_expr", K(ret));
} else if (expr->get_children_count() >= 2 && OB_NOT_NULL(expr = expr->get_param_expr(1))
&& expr->get_expr_type() == T_FUN_SYS_CAST && CM_IS_IMPLICIT_CAST(expr->get_extra())) {
do {
if (expr->get_children_count() >= 1
&& OB_ISNULL(expr = expr->get_param_expr(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to get_param_expr", K(ret));
}
} while (OB_SUCC(ret) && T_FUN_SYS_CAST == expr->get_expr_type()
&& CM_IS_IMPLICIT_CAST(expr->get_extra()));
if (OB_SUCC(ret)) {
len_obj = expr->get_result_type().get_param();
}
}
return ret;
}
int ObExprBaseLRpad::calc_type(ObExprResType &type,
ObExprResType &text,
ObExprResType &len,
ObExprResType *pad_text,
ObExprTypeCtx &type_ctx)
ObExprTypeCtx &type_ctx) const
{
int ret = OB_SUCCESS;
ObObjType text_type = ObNullType;
@ -248,9 +272,6 @@ int ObExprBaseLRpad::calc_type(ObExprResType &type,
len.set_calc_type(len_type);
if (is_mysql_mode()) {
pad_obj = pad_text->get_param();
type.set_type(text_type);
text.set_calc_type(text_type);
pad_text->set_calc_type(text_type);
ObSEArray<ObExprResType, 2> types;
OZ(types.push_back(text));
OZ(types.push_back(*pad_text));
@ -258,6 +279,28 @@ int ObExprBaseLRpad::calc_type(ObExprResType &type,
type_ctx.get_coll_type()));
OX(text.set_calc_collation_type(type.get_collation_type()));
OX(pad_text->set_calc_collation_type(type.get_collation_type()));
if (OB_SUCC(ret)) {
// len expr may add cast, search real len obj
if (OB_FAIL(get_origin_len_obj(length_obj))) {
LOG_WARN("fail to get ori len obj", K(ret));
} else if (!length_obj.is_null()) {
if (OB_FAIL(calc_type_length_mysql(type, text_obj, pad_obj, length_obj, type_ctx.get_session(), text_len))) {
LOG_WARN("failed to calc result type length mysql mode", K(ret));
}
} else {
text_len = max_len;
}
if (OB_SUCC(ret)) {
text_type = get_result_type_mysql(text_len);
type.set_type(text_type);
if (!ob_is_text_tc(text.get_type())) {
text.set_calc_type(text_type);
}
if (!ob_is_text_tc(pad_text->get_type())) {
pad_text->set_calc_type(text_type);
}
}
}
} else {
ObSEArray<ObExprResType*, 2> types;
OZ(types.push_back(&text));
@ -287,8 +330,6 @@ int ObExprBaseLRpad::calc_type(ObExprResType &type,
if (!length_obj.is_null()) {
if (is_oracle_mode && OB_FAIL(calc_type_length_oracle(type, text_obj, pad_obj, length_obj, text_len))) {
LOG_WARN("failed to calc result type length oracle mode", K(ret));
} else if (!is_oracle_mode && OB_FAIL(calc_type_length_mysql(type, text_obj, pad_obj, length_obj, type_ctx.get_session(), text_len))) {
LOG_WARN("failed to calc result type length mysql mode", K(ret));
}
} else {
text_len = max_len;
@ -640,6 +681,7 @@ int ObExprBaseLRpad::calc_mysql_inner(const LRpadType pad_type,
const ObCollationType cs_type = expr.datum_meta_.cs_type_;
const ObObjType type = expr.datum_meta_.type_;
bool has_lob_header = expr.obj_meta_.has_lob_header();
bool has_set_to_lob_locator = false;
int64_t int_len = len.get_int();
if (int_len < 0) {
res.set_null();
@ -652,7 +694,9 @@ int ObExprBaseLRpad::calc_mysql_inner(const LRpadType pad_type,
// only substr needed
result_size = ObCharset::charpos(cs_type, str_text.ptr(), str_text.length(), int_len);
res.set_string(ObString(result_size, str_text.ptr()));
} else if (str_pad.length() == 0) {
} else {
has_set_to_lob_locator = true;
if (str_pad.length() == 0) {
res.set_string(ObString::make_empty_string());
} else if (OB_FAIL(get_padding_info_mysql(cs_type, str_text, int_len, str_pad,
max_result_size, repeat_count, prefix_size, result_size))) {
@ -676,6 +720,22 @@ int ObExprBaseLRpad::calc_mysql_inner(const LRpadType pad_type,
res.set_string(result_ptr, result_size);
}
}
}
if (OB_SUCC(ret) && ob_is_text_tc(type) && !res.is_null() &&
has_lob_header && !has_set_to_lob_locator) {
ObString data = res.get_string();
ObTextStringResult result_buffer(type, has_lob_header, &res_alloc);
int64_t buffer_len = 0;
if (OB_FAIL(result_buffer.init(data.length()))) {
LOG_WARN("init stringtextbuffer failed", K(ret), K(data));
} else if (OB_FAIL(result_buffer.append(data))) {
LOG_WARN("temp lob lseek failed", K(ret));
} else {
ObString output;
result_buffer.get_result_buffer(output);
res.set_string(output);
}
}
return ret;
}

View File

@ -30,11 +30,11 @@ public:
virtual ~ObExprBaseLRpad();
static int calc_type(ObExprResType &type,
int calc_type(ObExprResType &type,
ObExprResType &text,
ObExprResType &len,
ObExprResType *pad_text,
common::ObExprTypeCtx &type_ctx);
common::ObExprTypeCtx &type_ctx) const;
static int padding(LRpadType type,
const common::ObCollationType coll_type,
@ -136,6 +136,7 @@ public:
static int calc_oracle(LRpadType pad_type, const ObExpr &expr, const common::ObDatum &text,
const common::ObDatum &len, const common::ObDatum &pad_text,
common::ObIAllocator &res_alloc, ObDatum &res, bool &is_unchanged_clob);
int get_origin_len_obj(ObObj &len_obj) const;
private:
DISALLOW_COPY_AND_ASSIGN(ObExprBaseLRpad);
};

View File

@ -46,7 +46,9 @@ int ObExprRepeat::calc_result_type2(ObExprResType &type,
ObExprTypeCtx &type_ctx) const
{
int ret = OB_SUCCESS;
if (!text.is_string_type()) {
text.set_calc_type(common::ObVarcharType);
}
count.set_calc_type(common::ObIntType);
// Set cast mode for %count parameter, truncate string to integer.
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_STRING_INTEGER_TRUNC);

View File

@ -26,7 +26,7 @@ namespace sql
{
using namespace common;
ObExprSpace::ObExprSpace(ObIAllocator &alloc)
: ObFuncExprOperator(alloc, T_FUN_SYS_SPACE, N_SPACE, 1, VALID_FOR_GENERATED_COL, NOT_ROW_DIMENSION) {}
: ObStringExprOperator(alloc, T_FUN_SYS_SPACE, N_SPACE, 1, VALID_FOR_GENERATED_COL) {}
inline int ObExprSpace::calc_result_type1(
ObExprResType &type,
@ -36,11 +36,41 @@ inline int ObExprSpace::calc_result_type1(
int ret = OB_SUCCESS;
// space is mysql only expr
CK(lib::is_mysql_mode());
type.set_type(ObVarcharType);
ObObjType res_type = ObMaxType;
if (type1.is_null()) {
res_type = ObVarcharType;
} else if (type1.is_literal()) {
const ObObj &obj = type1.get_param();
ObArenaAllocator alloc(ObModIds::OB_SQL_RES_TYPE);
const ObDataTypeCastParams dtc_params =
ObBasicSessionInfo::create_dtc_params(type_ctx.get_session());
int64_t cur_time = 0;
ObCastMode cast_mode = CM_NONE;
if (OB_FAIL(ObSQLUtils::get_default_cast_mode(type_ctx.get_session(), cast_mode))) {
LOG_WARN("failed to get default cast mode", K(ret));
} else {
cast_mode |= CM_WARN_ON_FAIL;
ObCastCtx cast_ctx(
&alloc, &dtc_params, cur_time, cast_mode, CS_TYPE_INVALID);
int64_t count_val = 0;
EXPR_GET_INT64_V2(obj, count_val);
res_type = get_result_type_mysql(count_val);
}
} else {
res_type = ObLongTextType;
}
type.set_type(res_type);
type.set_collation_level(type1.get_collation_level());
type.set_collation_type(get_default_collation_type(type.get_type(), *type_ctx.get_session()));
type.set_length(OB_MAX_VARCHAR_LENGTH);
if (ObVarcharType == type.get_type()) {
type.set_length(MAX_CHAR_LENGTH_FOR_VARCAHR_RESULT);
} else if (ob_is_text_tc(type.get_type())) {
const int32_t mbmaxlen = 4;
const int32_t default_text_length =
ObAccuracy::DDL_DEFAULT_ACCURACY[type.get_type()].get_length() / mbmaxlen;
// need to set a correct length for text tc in mysql mode
type.set_length(default_text_length);
}
type1.set_calc_type(ObIntType);
// Set cast mode for parameter casting, truncate string to integer.
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_STRING_INTEGER_TRUNC);

View File

@ -18,7 +18,7 @@ namespace oceanbase
{
namespace sql
{
class ObExprSpace : public ObFuncExprOperator
class ObExprSpace : public ObStringExprOperator
{
public:

View File

@ -82,3 +82,17 @@ select repeat(1.414, 2);
select repeat("abc", 200000000);
ERROR HY000: Result of repeat() was larger than max_allowed_packet (4194304) - truncated
drop table t2;
create table t2 as select repeat('a', 512),repeat('a', 513),repeat('a',32767),repeat('a',32768),repeat('a',65535),repeat('a',65536) from dual;
desc t2;
+-------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+-------+
| repeat('a', 512) | varchar(512) | YES | | NULL | |
| repeat('a', 513) | text | YES | | NULL | |
| repeat('a',32767) | text | YES | | NULL | |
| repeat('a',32768) | text | YES | | NULL | |
| repeat('a',65535) | text | YES | | NULL | |
| repeat('a',65536) | longtext | YES | | NULL | |
+-------------------+--------------+------+-----+---------+-------+
drop table t2;

View File

@ -33,6 +33,12 @@ select repeat(1.414, 2);
--error 1301
select repeat("abc", 200000000);
--error 0,1051
drop table t2;
create table t2 as select repeat('a', 512),repeat('a', 513),repeat('a',32767),repeat('a',32768),repeat('a',65535),repeat('a',65536) from dual;
desc t2;
drop table t2;
--enable_warnings
connection syscon;