expr repeat/space/lrpad opt for text type
This commit is contained in:
@ -198,11 +198,35 @@ int ObExprBaseLRpad::calc_type_length_oracle(const ObExprResType &result_type,
|
|||||||
return ret;
|
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,
|
int ObExprBaseLRpad::calc_type(ObExprResType &type,
|
||||||
ObExprResType &text,
|
ObExprResType &text,
|
||||||
ObExprResType &len,
|
ObExprResType &len,
|
||||||
ObExprResType *pad_text,
|
ObExprResType *pad_text,
|
||||||
ObExprTypeCtx &type_ctx)
|
ObExprTypeCtx &type_ctx) const
|
||||||
{
|
{
|
||||||
int ret = OB_SUCCESS;
|
int ret = OB_SUCCESS;
|
||||||
ObObjType text_type = ObNullType;
|
ObObjType text_type = ObNullType;
|
||||||
@ -248,9 +272,6 @@ int ObExprBaseLRpad::calc_type(ObExprResType &type,
|
|||||||
len.set_calc_type(len_type);
|
len.set_calc_type(len_type);
|
||||||
if (is_mysql_mode()) {
|
if (is_mysql_mode()) {
|
||||||
pad_obj = pad_text->get_param();
|
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;
|
ObSEArray<ObExprResType, 2> types;
|
||||||
OZ(types.push_back(text));
|
OZ(types.push_back(text));
|
||||||
OZ(types.push_back(*pad_text));
|
OZ(types.push_back(*pad_text));
|
||||||
@ -258,6 +279,28 @@ int ObExprBaseLRpad::calc_type(ObExprResType &type,
|
|||||||
type_ctx.get_coll_type()));
|
type_ctx.get_coll_type()));
|
||||||
OX(text.set_calc_collation_type(type.get_collation_type()));
|
OX(text.set_calc_collation_type(type.get_collation_type()));
|
||||||
OX(pad_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 {
|
} else {
|
||||||
ObSEArray<ObExprResType*, 2> types;
|
ObSEArray<ObExprResType*, 2> types;
|
||||||
OZ(types.push_back(&text));
|
OZ(types.push_back(&text));
|
||||||
@ -287,8 +330,6 @@ int ObExprBaseLRpad::calc_type(ObExprResType &type,
|
|||||||
if (!length_obj.is_null()) {
|
if (!length_obj.is_null()) {
|
||||||
if (is_oracle_mode && OB_FAIL(calc_type_length_oracle(type, text_obj, pad_obj, length_obj, text_len))) {
|
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));
|
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 {
|
} else {
|
||||||
text_len = max_len;
|
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 ObCollationType cs_type = expr.datum_meta_.cs_type_;
|
||||||
const ObObjType type = expr.datum_meta_.type_;
|
const ObObjType type = expr.datum_meta_.type_;
|
||||||
bool has_lob_header = expr.obj_meta_.has_lob_header();
|
bool has_lob_header = expr.obj_meta_.has_lob_header();
|
||||||
|
bool has_set_to_lob_locator = false;
|
||||||
int64_t int_len = len.get_int();
|
int64_t int_len = len.get_int();
|
||||||
if (int_len < 0) {
|
if (int_len < 0) {
|
||||||
res.set_null();
|
res.set_null();
|
||||||
@ -652,28 +694,46 @@ int ObExprBaseLRpad::calc_mysql_inner(const LRpadType pad_type,
|
|||||||
// only substr needed
|
// only substr needed
|
||||||
result_size = ObCharset::charpos(cs_type, str_text.ptr(), str_text.length(), int_len);
|
result_size = ObCharset::charpos(cs_type, str_text.ptr(), str_text.length(), int_len);
|
||||||
res.set_string(ObString(result_size, str_text.ptr()));
|
res.set_string(ObString(result_size, str_text.ptr()));
|
||||||
} else 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))) {
|
|
||||||
LOG_WARN("Failed to get padding info", K(ret), K(str_text), K(int_len),
|
|
||||||
K(str_pad), K(max_result_size));
|
|
||||||
} else if (result_size > max_result_size) {
|
|
||||||
res.set_null();
|
|
||||||
if (pad_type == RPAD_TYPE) {
|
|
||||||
LOG_USER_WARN(OB_ERR_FUNC_RESULT_TOO_LARGE, "rpad", static_cast<int>(max_result_size));
|
|
||||||
} else {
|
|
||||||
LOG_USER_WARN(OB_ERR_FUNC_RESULT_TOO_LARGE, "lpad", static_cast<int>(max_result_size));
|
|
||||||
}
|
|
||||||
} else if (OB_FAIL(padding(pad_type, cs_type, str_text.ptr(), str_text.length(), str_pad.ptr(),
|
|
||||||
str_pad.length(), prefix_size, repeat_count, false, &res_alloc,
|
|
||||||
result_ptr, result_size, type, has_lob_header))) {
|
|
||||||
LOG_WARN("Failed to pad", K(ret), K(str_text), K(str_pad), K(prefix_size), K(repeat_count));
|
|
||||||
} else {
|
} else {
|
||||||
if (NULL == result_ptr || 0 == result_size) {
|
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))) {
|
||||||
|
LOG_WARN("Failed to get padding info", K(ret), K(str_text), K(int_len),
|
||||||
|
K(str_pad), K(max_result_size));
|
||||||
|
} else if (result_size > max_result_size) {
|
||||||
res.set_null();
|
res.set_null();
|
||||||
|
if (pad_type == RPAD_TYPE) {
|
||||||
|
LOG_USER_WARN(OB_ERR_FUNC_RESULT_TOO_LARGE, "rpad", static_cast<int>(max_result_size));
|
||||||
|
} else {
|
||||||
|
LOG_USER_WARN(OB_ERR_FUNC_RESULT_TOO_LARGE, "lpad", static_cast<int>(max_result_size));
|
||||||
|
}
|
||||||
|
} else if (OB_FAIL(padding(pad_type, cs_type, str_text.ptr(), str_text.length(), str_pad.ptr(),
|
||||||
|
str_pad.length(), prefix_size, repeat_count, false, &res_alloc,
|
||||||
|
result_ptr, result_size, type, has_lob_header))) {
|
||||||
|
LOG_WARN("Failed to pad", K(ret), K(str_text), K(str_pad), K(prefix_size), K(repeat_count));
|
||||||
} else {
|
} else {
|
||||||
res.set_string(result_ptr, result_size);
|
if (NULL == result_ptr || 0 == result_size) {
|
||||||
|
res.set_null();
|
||||||
|
} else {
|
||||||
|
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;
|
return ret;
|
||||||
|
|||||||
@ -30,11 +30,11 @@ public:
|
|||||||
|
|
||||||
virtual ~ObExprBaseLRpad();
|
virtual ~ObExprBaseLRpad();
|
||||||
|
|
||||||
static int calc_type(ObExprResType &type,
|
int calc_type(ObExprResType &type,
|
||||||
ObExprResType &text,
|
ObExprResType &text,
|
||||||
ObExprResType &len,
|
ObExprResType &len,
|
||||||
ObExprResType *pad_text,
|
ObExprResType *pad_text,
|
||||||
common::ObExprTypeCtx &type_ctx);
|
common::ObExprTypeCtx &type_ctx) const;
|
||||||
|
|
||||||
static int padding(LRpadType type,
|
static int padding(LRpadType type,
|
||||||
const common::ObCollationType coll_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,
|
static int calc_oracle(LRpadType pad_type, const ObExpr &expr, const common::ObDatum &text,
|
||||||
const common::ObDatum &len, const common::ObDatum &pad_text,
|
const common::ObDatum &len, const common::ObDatum &pad_text,
|
||||||
common::ObIAllocator &res_alloc, ObDatum &res, bool &is_unchanged_clob);
|
common::ObIAllocator &res_alloc, ObDatum &res, bool &is_unchanged_clob);
|
||||||
|
int get_origin_len_obj(ObObj &len_obj) const;
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(ObExprBaseLRpad);
|
DISALLOW_COPY_AND_ASSIGN(ObExprBaseLRpad);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -46,7 +46,9 @@ int ObExprRepeat::calc_result_type2(ObExprResType &type,
|
|||||||
ObExprTypeCtx &type_ctx) const
|
ObExprTypeCtx &type_ctx) const
|
||||||
{
|
{
|
||||||
int ret = OB_SUCCESS;
|
int ret = OB_SUCCESS;
|
||||||
text.set_calc_type(common::ObVarcharType);
|
if (!text.is_string_type()) {
|
||||||
|
text.set_calc_type(common::ObVarcharType);
|
||||||
|
}
|
||||||
count.set_calc_type(common::ObIntType);
|
count.set_calc_type(common::ObIntType);
|
||||||
// Set cast mode for %count parameter, truncate string to integer.
|
// Set cast mode for %count parameter, truncate string to integer.
|
||||||
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_STRING_INTEGER_TRUNC);
|
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_STRING_INTEGER_TRUNC);
|
||||||
|
|||||||
@ -26,7 +26,7 @@ namespace sql
|
|||||||
{
|
{
|
||||||
using namespace common;
|
using namespace common;
|
||||||
ObExprSpace::ObExprSpace(ObIAllocator &alloc)
|
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(
|
inline int ObExprSpace::calc_result_type1(
|
||||||
ObExprResType &type,
|
ObExprResType &type,
|
||||||
@ -36,11 +36,41 @@ inline int ObExprSpace::calc_result_type1(
|
|||||||
int ret = OB_SUCCESS;
|
int ret = OB_SUCCESS;
|
||||||
// space is mysql only expr
|
// space is mysql only expr
|
||||||
CK(lib::is_mysql_mode());
|
CK(lib::is_mysql_mode());
|
||||||
|
ObObjType res_type = ObMaxType;
|
||||||
type.set_type(ObVarcharType);
|
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_level(type1.get_collation_level());
|
||||||
type.set_collation_type(get_default_collation_type(type.get_type(), *type_ctx.get_session()));
|
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);
|
type1.set_calc_type(ObIntType);
|
||||||
// Set cast mode for parameter casting, truncate string to integer.
|
// Set cast mode for parameter casting, truncate string to integer.
|
||||||
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_STRING_INTEGER_TRUNC);
|
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_STRING_INTEGER_TRUNC);
|
||||||
|
|||||||
@ -18,7 +18,7 @@ namespace oceanbase
|
|||||||
{
|
{
|
||||||
namespace sql
|
namespace sql
|
||||||
{
|
{
|
||||||
class ObExprSpace : public ObFuncExprOperator
|
class ObExprSpace : public ObStringExprOperator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@ -82,3 +82,17 @@ select repeat(1.414, 2);
|
|||||||
select repeat("abc", 200000000);
|
select repeat("abc", 200000000);
|
||||||
ERROR HY000: Result of repeat() was larger than max_allowed_packet (4194304) - truncated
|
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;
|
||||||
|
|||||||
@ -33,6 +33,12 @@ select repeat(1.414, 2);
|
|||||||
--error 1301
|
--error 1301
|
||||||
select repeat("abc", 200000000);
|
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
|
--enable_warnings
|
||||||
|
|
||||||
connection syscon;
|
connection syscon;
|
||||||
|
|||||||
Reference in New Issue
Block a user