Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
野花太放肆
oceanbase
提交
e88e59a6
O
oceanbase
项目概览
野花太放肆
/
oceanbase
与 Fork 源项目一致
Fork自
oceanbase / oceanbase
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
oceanbase
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e88e59a6
编写于
2月 23, 2023
作者:
A
AntiTopQuark
提交者:
ob-robot
2月 23, 2023
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[CP] fix bug of weight_string
上级
ff557a58
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
159 addition
and
87 deletion
+159
-87
src/sql/engine/expr/ob_expr_weight_string.cpp
src/sql/engine/expr/ob_expr_weight_string.cpp
+159
-87
未找到文件。
src/sql/engine/expr/ob_expr_weight_string.cpp
浏览文件 @
e88e59a6
...
...
@@ -21,6 +21,8 @@
#include "lib/oblog/ob_log.h"
#include "sql/engine/expr/ob_datum_cast.h"
#include "ob_expr_util.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/session/ob_sql_session_info.h"
using
namespace
oceanbase
::
common
;
...
...
@@ -46,20 +48,24 @@ int ObExprWeightString::calc_result_typeN(ObExprResType &type,
if
(
NOT_ROW_DIMENSION
!=
row_dimension_
||
ObMaxType
==
types_stack
[
0
].
get_type
())
{
ret
=
OB_ERR_INVALID_TYPE_FOR_OP
;
}
else
{
if
(
types_stack
[
0
].
get_type
()
>
ObUNumberType
)
{
// 输入不是数字类型时
type_ctx
.
set_cast_mode
(
type_ctx
.
get_cast_mode
()
|
CM_NULL_ON_WARN
);
types_stack
[
0
].
set_calc_type
(
ObVarcharType
);
}
int
max_length
=
OB_MAX_VARBINARY_LENGTH
;
// The maximum length of the result of WEIGHT_STRING()
int
result_length
=
types_stack
[
1
].
get_param
().
get_int
();
int
nweight
=
types_stack
[
2
].
get_param
().
get_int
();
uint64_t
max_length
=
OB_MAX_VARBINARY_LENGTH
;
// The maximum length of the result of WEIGHT_STRING()
uint64_t
result_length
=
types_stack
[
1
].
get_param
().
get_int
();
uint64_t
nweight
=
types_stack
[
2
].
get_param
().
get_int
();
bool
as_binary
=
types_stack
[
4
].
get_param
().
get_int
();
ObCollationLevel
coll_level
=
CS_LEVEL_INVALID
;
if
(
as_binary
)
{
coll_level
=
CS_LEVEL_IMPLICIT
;
type_ctx
.
set_cast_mode
(
type_ctx
.
get_cast_mode
()
|
CM_NULL_ON_WARN
);
types_stack
[
0
].
set_calc_type
(
ObVarcharType
);
}
else
{
coll_level
=
types_stack
[
0
].
get_collation_level
();
if
(
types_stack
[
0
].
get_type
()
>
ObUNumberType
&&
types_stack
[
0
].
get_type
()
!=
ObBitType
&&
types_stack
[
0
].
get_type
()
!=
ObYearType
)
{
// When the input is not a numeric type, convert to a varchar type
type_ctx
.
set_cast_mode
(
type_ctx
.
get_cast_mode
()
|
CM_NULL_ON_WARN
);
types_stack
[
0
].
set_calc_type
(
ObVarcharType
);
}
}
ObCollationType
collation_type
=
types_stack
[
0
].
get_collation_type
();
const
ObCharsetInfo
*
cs
=
ObCharset
::
get_charset
(
collation_type
);
...
...
@@ -67,19 +73,17 @@ int ObExprWeightString::calc_result_typeN(ObExprResType &type,
types_stack
[
0
].
get_type
()
==
ObTimestampType
||
types_stack
[
0
].
get_type
()
==
ObDateType
||
types_stack
[
0
].
get_type
()
==
ObTimeType
)
{
//
日期、时间等类型,max_lenght是输入的类型的长度
//
For types such as date, time, etc., the max_lenght is the length of the type entered
max_length
=
types_stack
[
0
].
get_length
();
}
else
if
(
result_length
>
0
)
{
max_length
=
result_length
;
}
else
if
(
as_binary
)
{
//
as_binary的情况下,以nweight作为输出结果的max_length
//
In the case of as_binary, the max_length with nweight as the output result
max_length
=
nweight
;
}
else
{
//
输入为 char的情况下,使用cs->mbmaxlen计算
max_length
max_length
=
cs
->
mbmaxlen
*
max
(
nweight
,
types_stack
[
0
].
get_length
()
*
cs
->
mbmaxlen
);
//
If the input is others, use cs->mbmaxlen to calculate the
max_length
max_length
=
cs
->
mbmaxlen
*
MAX
(
nweight
,
types_stack
[
0
].
get_length
()
*
cs
->
mbmaxlen
);
}
ObObj
aaa
=
types_stack
[
0
].
get_param
();
// 推导结果
type
.
set_varchar
();
type
.
set_collation_type
(
CS_TYPE_BINARY
);
type
.
set_collation_level
(
coll_level
);
...
...
@@ -105,44 +109,80 @@ int ObExprWeightString::calc_resultN(common::ObObj &result , const common::ObObj
result
.
set_null
();
}
else
{
const
ObString
str
=
objs_array
[
0
].
get_string
();
in
t
result_length
=
objs_array
[
1
].
get_int
();
in
t
nweights
=
objs_array
[
2
].
get_int
();
in
t
flags
=
objs_array
[
3
].
get_int
();
uint64_
t
result_length
=
objs_array
[
1
].
get_int
();
uint64_
t
nweights
=
objs_array
[
2
].
get_int
();
uint64_
t
flags
=
objs_array
[
3
].
get_int
();
bool
as_binary
=
objs_array
[
4
].
get_int
();
ObCollationType
collation_type
=
CS_TYPE_INVALID
;
if
(
as_binary
)
{
collation_type
=
CS_TYPE_BINARY
;
}
else
{
collation_type
=
objs_array
[
0
].
get_collation_type
();
}
const
ObCharsetInfo
*
cs
=
ObCharset
::
get_charset
(
collation_type
);
flags
=
ob_strxfrm_flag_normalize
(
flags
,
cs
->
levels_for_order
);
// calc the length of result
size_t
frm_length
=
0
;
size_t
tmp_length
=
0
;
if
(
result_length
>
0
)
{
tmp_length
=
result_length
;
}
else
{
tmp_length
=
cs
->
coll
->
strnxfrmlen
(
cs
,
cs
->
mbmaxlen
*
max
(
str
.
length
()
,
nweights
));
}
int
is_valid_unicode_tmp
=
1
;
char
*
out_buf
;
if
(
OB_ISNULL
(
out_buf
=
static_cast
<
char
*>
(
expr_ctx
.
calc_buf_
->
alloc
(
tmp_length
))))
{
int64_t
max_allowed_packet
=
0
;
ObSQLSessionInfo
*
session
=
expr_ctx
.
exec_ctx_
->
get_my_session
();
if
(
!
as_binary
&&
(
objs_array
[
0
].
get_type
()
<=
ObUNumberType
||
objs_array
[
0
].
get_type
()
==
ObBitType
||
objs_array
[
0
].
get_type
()
==
ObYearType
))
{
result
.
set_null
();
ret
=
OB_ALLOCATE_MEMORY_FAILED
;
LOG_ERROR
(
"alloc memory failed"
,
K
(
ret
),
K
(
out_buf
),
K
(
tmp_length
)
);
}
else
if
(
str
.
empty
()
&&
nweights
==
0
)
{
result
.
set_varchar
(
nullptr
,
0
);
}
else
{
frm_length
=
cs
->
coll
->
strnxfrm
(
cs
,
reinterpret_cast
<
uchar
*>
(
out_buf
),
tmp_length
,
nweights
?
nweights
:
tmp_length
,
reinterpret_cast
<
const
uchar
*>
(
str
.
ptr
()),
str
.
length
(),
flags
,
&
is_valid_unicode_tmp
);
result
.
set_varchar
(
out_buf
,
frm_length
);
if
(
OB_FAIL
(
session
->
get_max_allowed_packet
(
max_allowed_packet
)))
{
if
(
OB_ENTRY_NOT_EXIST
==
ret
)
{
ret
=
OB_SUCCESS
;
max_allowed_packet
=
OB_MAX_VARCHAR_LENGTH
;
}
else
{
LOG_WARN
(
"Failed to get max allow packet size"
,
K
(
ret
));
}
}
// Get the character set and collation information of the input string
ObCollationType
collation_type
=
CS_TYPE_INVALID
;
if
(
as_binary
)
{
collation_type
=
CS_TYPE_BINARY
;
}
else
{
collation_type
=
objs_array
[
0
].
get_collation_type
();
}
const
ObCharsetInfo
*
cs
=
ObCharset
::
get_charset
(
collation_type
);
flags
=
ob_strxfrm_flag_normalize
(
flags
,
cs
->
levels_for_order
);
// calc the length of result
size_t
frm_length
=
0
;
size_t
tmp_length
=
0
;
if
(
result_length
>
0
)
{
tmp_length
=
result_length
;
}
else
{
tmp_length
=
cs
->
coll
->
strnxfrmlen
(
cs
,
cs
->
mbmaxlen
*
MAX
(
str
.
length
()
,
nweights
));
}
if
(
tmp_length
>=
max_allowed_packet
)
{
// The return result exceeds the maximum limit and returns NULL.
result
.
set_null
();
}
else
{
int
is_valid_unicode_tmp
=
1
;
// For the case where the input is an empty string but the nweight is not 0,
// the weight_string function will call strnxfrm() to padding the result
// eg:
// mysql> select HEX(WEIGHT_STRING('' as char(3)));
// +-----------------------------------+
// | HEX(WEIGHT_STRING('' as char(3))) |
// +-----------------------------------+
// | 002000200020 |
// +-----------------------------------+
// However, the strnxfrm requires that the input cannot be a null ptr,
// so an empty string is set as the input.
const
char
*
tmp_empty_str
=
""
;
char
*
out_buf
;
if
(
OB_ISNULL
(
out_buf
=
static_cast
<
char
*>
(
expr_ctx
.
calc_buf_
->
alloc
(
tmp_length
))))
{
result
.
set_null
();
ret
=
OB_ALLOCATE_MEMORY_FAILED
;
LOG_WARN
(
"failed to alloc output buf"
,
K
(
ret
));
}
else
{
frm_length
=
cs
->
coll
->
strnxfrm
(
cs
,
reinterpret_cast
<
uchar
*>
(
out_buf
),
tmp_length
,
nweights
?
nweights
:
tmp_length
,
str
.
ptr
()
!=
NULL
?
reinterpret_cast
<
const
uchar
*>
(
str
.
ptr
())
:
reinterpret_cast
<
const
uchar
*>
(
tmp_empty_str
),
str
.
length
(),
flags
,
&
is_valid_unicode_tmp
);
result
.
set_varchar
(
out_buf
,
frm_length
);
}
}
}
}
}
}
else
{
ret
=
OB_INVALID_ARGUMENT_NUM
;
result
.
set_null
();
...
...
@@ -170,49 +210,81 @@ int ObExprWeightString::eval_weight_string(const ObExpr &expr, ObEvalCtx &ctx, O
KP
(
nweights_arg
),
KP
(
flags_arg
),
KP
(
as_binary_arg
));
}
else
if
(
arg
->
is_null
()
||
arg
->
get_string
()
==
NULL
||
expr
.
args_
[
0
]
->
datum_meta_
.
type_
<=
ObUNumberType
)
{
// The input string is NULL or numeric
res_datum
.
set_null
();
}
else
{
const
ObString
str
=
arg
->
get_string
();
in
t
result_length
=
result_length_arg
->
get_int
();
in
t
nweights
=
nweights_arg
->
get_int
();
in
t
flags
=
flags_arg
->
get_int
();
uint64_
t
result_length
=
result_length_arg
->
get_int
();
uint64_
t
nweights
=
nweights_arg
->
get_int
();
uint64_
t
flags
=
flags_arg
->
get_int
();
bool
as_binary
=
as_binary_arg
->
get_int
();
// Get the character set and collation information of the input string
ObCollationType
collation_type
=
CS_TYPE_INVALID
;
if
(
as_binary
)
{
collation_type
=
CS_TYPE_BINARY
;
int64_t
max_allowed_packet
=
0
;
ObSQLSessionInfo
*
session
=
ctx
.
exec_ctx_
.
get_my_session
();
if
(
arg
->
is_null
())
{
res_datum
.
set_null
();
}
else
if
(
!
as_binary
&&
(
expr
.
args_
[
0
]
->
datum_meta_
.
type_
<=
ObUNumberType
||
expr
.
args_
[
0
]
->
datum_meta_
.
type_
==
ObBitType
||
expr
.
args_
[
0
]
->
datum_meta_
.
type_
==
ObYearType
))
{
res_datum
.
set_null
();
}
else
if
(
arg
->
get_string
().
empty
()
&&
nweights
==
0
)
{
res_datum
.
set_string
(
nullptr
,
0
);
}
else
{
collation_type
=
expr
.
args_
[
0
]
->
datum_meta_
.
cs_type_
;
}
const
ObCharsetInfo
*
cs
=
ObCharset
::
get_charset
(
collation_type
);
flags
=
ob_strxfrm_flag_normalize
(
flags
,
cs
->
levels_for_order
);
// calc the length of result
size_t
frm_length
=
0
;
size_t
tmp_length
=
0
;
if
(
result_length
>
0
)
{
tmp_length
=
result_length
;
}
else
{
tmp_length
=
cs
->
coll
->
strnxfrmlen
(
cs
,
cs
->
mbmaxlen
*
max
(
str
.
length
()
,
nweights
));
}
int
is_valid_unicode_tmp
=
1
;
char
*
out_buf
=
expr
.
get_str_res_mem
(
ctx
,
tmp_length
);
if
(
OB_ISNULL
(
out_buf
))
{
ret
=
OB_ALLOCATE_MEMORY_FAILED
;
}
else
{
frm_length
=
cs
->
coll
->
strnxfrm
(
cs
,
reinterpret_cast
<
uchar
*>
(
out_buf
),
tmp_length
,
nweights
?
nweights
:
tmp_length
,
reinterpret_cast
<
const
uchar
*>
(
str
.
ptr
()),
str
.
length
(),
flags
,
&
is_valid_unicode_tmp
);
res_datum
.
set_string
(
out_buf
,
frm_length
);
if
(
OB_FAIL
(
session
->
get_max_allowed_packet
(
max_allowed_packet
)))
{
if
(
OB_ENTRY_NOT_EXIST
==
ret
)
{
ret
=
OB_SUCCESS
;
max_allowed_packet
=
OB_MAX_VARCHAR_LENGTH
;
}
else
{
LOG_WARN
(
"Failed to get max allow packet size"
,
K
(
ret
));
}
}
// Get the character set and collation information of the input string
ObCollationType
collation_type
=
CS_TYPE_INVALID
;
if
(
as_binary
)
{
collation_type
=
CS_TYPE_BINARY
;
}
else
{
collation_type
=
expr
.
args_
[
0
]
->
datum_meta_
.
cs_type_
;
}
const
ObCharsetInfo
*
cs
=
ObCharset
::
get_charset
(
collation_type
);
flags
=
ob_strxfrm_flag_normalize
(
flags
,
cs
->
levels_for_order
);
// calc the length of result
size_t
frm_length
=
0
;
size_t
tmp_length
=
0
;
if
(
result_length
>
0
)
{
tmp_length
=
result_length
;
}
else
{
tmp_length
=
cs
->
coll
->
strnxfrmlen
(
cs
,
cs
->
mbmaxlen
*
MAX
(
str
.
length
()
,
nweights
));
}
if
(
tmp_length
>=
max_allowed_packet
)
{
// The return result exceeds the maximum limit and returns NULL.
res_datum
.
set_null
();
}
else
{
int
is_valid_unicode_tmp
=
1
;
char
*
out_buf
=
expr
.
get_str_res_mem
(
ctx
,
tmp_length
);
// For the case where the input is an empty string but the nweight is not 0,
// the weight_string function will call strnxfrm() to padding the result
// eg:
// mysql> select HEX(WEIGHT_STRING('' as char(3)));
// +-----------------------------------+
// | HEX(WEIGHT_STRING('' as char(3))) |
// +-----------------------------------+
// | 002000200020 |
// +-----------------------------------+
// However, the strnxfrm requires that the input cannot be a null ptr,
// so an empty string is set as the input.
const
char
*
tmp_empty_str
=
""
;
if
(
OB_ISNULL
(
out_buf
))
{
ret
=
OB_ALLOCATE_MEMORY_FAILED
;
LOG_WARN
(
"failed to alloc output buf"
,
K
(
ret
));
}
else
{
frm_length
=
cs
->
coll
->
strnxfrm
(
cs
,
reinterpret_cast
<
uchar
*>
(
out_buf
),
tmp_length
,
nweights
?
nweights
:
tmp_length
,
str
.
ptr
()
!=
NULL
?
reinterpret_cast
<
const
uchar
*>
(
str
.
ptr
())
:
reinterpret_cast
<
const
uchar
*>
(
tmp_empty_str
),
str
.
length
(),
flags
,
&
is_valid_unicode_tmp
);
res_datum
.
set_string
(
out_buf
,
frm_length
);
}
}
}
}
return
ret
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录