fix:json-remove, json is true/false, json-length bug

This commit is contained in:
obdev
2024-01-22 12:12:52 +00:00
committed by ob-robot
parent 240e147747
commit 9237df7de1
16 changed files with 149 additions and 18 deletions

View File

@ -1117,6 +1117,8 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
NULL, //ObExprInnerTableSequenceGetter::eval_inner_table_sequence_getter, /* 673 */
NULL, //ObExprDecodeTraceId::calc_decode_trace_id_expr, /* 674 */
ObExprInnerRowCmpVal::eval_inner_row_cmp_val, /* 675 */
ObExprIs::json_is_true, /* 676 */
ObExprIs::json_is_false, /* 677 */
};
static ObExpr::EvalBatchFunc g_expr_eval_batch_functions[] = {

View File

@ -13,6 +13,7 @@
#define USING_LOG_PREFIX SQL_ENG
#include <math.h>
#include "sql/engine/expr/ob_expr_is.h"
#include "ob_expr_json_func_helper.h"
#include "share/object/ob_obj_cast.h"
//#include "sql/engine/expr/ob_expr_promotion_util.h"
#include "objit/common/ob_item_type.h"
@ -67,6 +68,9 @@ int ObExprIsBase::calc_result_type2(ObExprResType &type,
if (ob_is_numeric_type(type1.get_type())) {
type1.set_calc_meta(type1.get_obj_meta());
type1.set_calc_accuracy(type1.get_accuracy());
} else if (ob_is_json(type1.get_type())) {
type1.set_calc_meta(type1.get_obj_meta());
type1.set_calc_accuracy(type1.get_accuracy());
} else {
type1.set_calc_type(ObNumberType);
const ObAccuracy &calc_acc = ObAccuracy::DDL_DEFAULT_ACCURACY2[0][ObNumberType];
@ -246,6 +250,10 @@ int ObExprIsBase::cg_result_type_class(ObObjType type, ObExpr::EvalFunc &eval_fu
EVAL_FUNC(decimal_int);
break;
}
case ObJsonType: {
EVAL_FUNC(json);
break;
}
case ObMaxType: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("is expr got unexpected type param", K(ret), K(type));
@ -542,6 +550,7 @@ NUMERIC_CALC_FUNC(float, ObExprIsNot, true, true, is_not)
NUMERIC_CALC_FUNC(double, ObExprIsNot, true, true, is_not)
NUMERIC_CALC_FUNC(number, ObExprIsNot, true, true, is_not)
NUMERIC_CALC_FUNC(decimal_int, ObExprIsNot, true, true, is_not)
NUMERIC_CALC_FUNC(json, ObExprIsNot, true, true, is_not)
NUMERIC_CALC_FUNC(int, ObExprIsNot, true, false, is_not)
@ -549,18 +558,21 @@ NUMERIC_CALC_FUNC(float, ObExprIsNot, true, false, is_not)
NUMERIC_CALC_FUNC(double, ObExprIsNot, true, false, is_not)
NUMERIC_CALC_FUNC(number, ObExprIsNot, true, false, is_not)
NUMERIC_CALC_FUNC(decimal_int, ObExprIsNot, true, false, is_not)
NUMERIC_CALC_FUNC(json, ObExprIsNot, true, false, is_not)
NUMERIC_CALC_FUNC(int, ObExprIs, false, true, is)
NUMERIC_CALC_FUNC(float, ObExprIs, false, true, is)
NUMERIC_CALC_FUNC(double, ObExprIs, false, true, is)
NUMERIC_CALC_FUNC(number, ObExprIs, false, true, is)
NUMERIC_CALC_FUNC(decimal_int, ObExprIs, false, true, is)
NUMERIC_CALC_FUNC(json, ObExprIs, false, true, is)
NUMERIC_CALC_FUNC(int, ObExprIs, false, false, is)
NUMERIC_CALC_FUNC(float, ObExprIs, false, false, is)
NUMERIC_CALC_FUNC(double, ObExprIs, false, false, is)
NUMERIC_CALC_FUNC(number, ObExprIs, false, false, is)
NUMERIC_CALC_FUNC(decimal_int, ObExprIs, false, false, is)
NUMERIC_CALC_FUNC(json, ObExprIs, false, false, is)
}
}

View File

@ -72,6 +72,8 @@ class ObExprIs: public ObExprIsBase
static int calc_is_null(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int int_is_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int int_is_false(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int json_is_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int json_is_false(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int float_is_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int float_is_false(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int double_is_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
@ -106,6 +108,8 @@ public:
static int calc_is_not_null(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int int_is_not_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int int_is_not_false(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int json_is_not_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int json_is_not_false(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int float_is_not_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int float_is_not_false(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
static int double_is_not_true(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);

View File

@ -56,7 +56,10 @@ int ObExprJsonArray::calc_result_typeN(ObExprResType& type,
type.set_length((ObAccuracy::DDL_DEFAULT_ACCURACY[ObJsonType]).get_length());
for (int64_t i = 0; i < param_num; i++) {
if (ob_is_string_type(types_stack[i].get_type())) {
if (types_stack[i].get_charset_type() != CHARSET_UTF8MB4) {
if (types_stack[i].get_type() == ObVarcharType && types_stack[i].get_collation_type() == CS_TYPE_BINARY) {
types_stack[i].set_calc_type(ObHexStringType);
types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN);
} else if (types_stack[i].get_charset_type() != CHARSET_UTF8MB4) {
types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN);
}
} else if (types_stack[i].get_type() == ObJsonType) {
@ -270,7 +273,6 @@ int ObExprJsonArray::eval_json_array(const ObExpr &expr, ObEvalCtx &ctx, ObDatum
for (uint32_t i = 0; OB_SUCC(ret) && i < expr.arg_cnt_; i++) {
ObIJsonBase *j_val;
if (OB_FAIL(ObJsonExprHelper::get_json_val(expr, ctx, &temp_allocator, i, j_val))) {
ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM;
LOG_WARN("failed: get_json_val failed", K(ret));
} else if (OB_FAIL(j_base->array_append(j_val))) {
LOG_WARN("failed: json array append json value", K(ret));

View File

@ -306,6 +306,10 @@ int ObJsonExprHelper::get_json_val(const ObExpr &expr, ObEvalCtx &ctx,
LOG_WARN("failed: parse value to jsonBase", K(ret), K(val_type));
}
}
if (OB_SUCC(ret) && OB_NOT_NULL(j_base)) {
j_base->set_allocator(allocator);
}
return ret;
}
int ObJsonExprHelper::eval_oracle_json_val(ObExpr *expr,
@ -762,7 +766,10 @@ void ObJsonExprHelper::set_type_for_value(ObExprResType* types_stack, uint32_t i
ObObjType in_type = types_stack[index].get_type();
if (in_type == ObNullType) {
} else if (ob_is_string_type(in_type)) {
if (types_stack[index].get_charset_type() != CHARSET_UTF8MB4) {
if (in_type == ObVarcharType && types_stack[index].get_collation_type() == CS_TYPE_BINARY) {
types_stack[index].set_calc_type(ObHexStringType);
types_stack[index].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN);
} else if (types_stack[index].get_charset_type() != CHARSET_UTF8MB4) {
types_stack[index].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN);
}
} else if (in_type == ObJsonType) {
@ -787,6 +794,37 @@ int ObJsonExprHelper::is_json_zero(const ObString& data, int& result)
return ret;
}
int ObJsonExprHelper::is_json_true(const ObString& data, int& result)
{
INIT_SUCC(ret);
int tmp_result = 0;
ObJsonBin j_bin(data.ptr(), data.length());
if (data.length() == 0) {
result = 0;
} else if (OB_FAIL(j_bin.reset_iter())) {
LOG_WARN("failed: reset iter", K(ret));
} else if ((j_bin.json_type() == ObJsonNodeType::J_OBJECT ||
j_bin.json_type() == ObJsonNodeType::J_ARRAY ||
j_bin.json_type() == ObJsonNodeType::J_STRING ||
j_bin.json_type() == ObJsonNodeType::J_NULL ||
j_bin.json_type() == ObJsonNodeType::J_BOOLEAN)) {
result = 1;
} else if ((j_bin.json_type() == ObJsonNodeType::J_INT || j_bin.json_type() == ObJsonNodeType::J_UINT)
&& OB_FAIL(ObJsonBaseUtil::compare_int_json(0, &j_bin, tmp_result))) {
LOG_WARN("failed: cmp json", K(ret));
} else if ((j_bin.json_type() == ObJsonNodeType::J_DECIMAL)
&& OB_FAIL(ObJsonBaseUtil::compare_decimal_uint(j_bin.get_decimal_data(), 0, tmp_result))) {
LOG_WARN("failed: cmp json", K(ret));
} else if ((j_bin.json_type() == ObJsonNodeType::J_DOUBLE)
&& OB_FAIL(ObJsonBaseUtil::compare_double_int(j_bin.get_double(), 0, tmp_result))) {
LOG_WARN("failed: cmp json", K(ret));
} else {
result = (tmp_result == 0) ? 0 : 1;
}
return ret;
}
template <typename T>
int ObJsonExprHelper::transform_scalar_2jsonBase(const T &datum,
ObObjType type,

View File

@ -116,6 +116,8 @@ public:
static ObJsonPathCache* get_path_cache_ctx(const uint64_t& id, ObExecContext *exec_ctx);
static int is_json_zero(const ObString& data, int& result);
static int is_json_true(const ObString& data, int& result);
/*
try to transfrom scalar data to jsonBase

View File

@ -108,13 +108,15 @@ int ObExprJsonLength::calc(ObEvalCtx &ctx, const ObDatum &data1, ObDatumMeta met
ObJsonPath *j_path = NULL;
if (OB_FAIL(ObTextStringHelper::read_real_string_data(*allocator, *data2, meta2, has_lob_header2, j_path_text))) {
LOG_WARN("fail to get real data.", K(ret), K(j_path_text));
} else if (OB_FAIL(ObJsonExprHelper::find_and_add_cache(path_cache, j_path, j_path_text, 1, false))) {
} else if (OB_FAIL(ObJsonExprHelper::find_and_add_cache(path_cache, j_path, j_path_text, 1, true))) {
LOG_USER_ERROR(OB_ERR_INVALID_JSON_PATH);
LOG_WARN("fail to parse json path", K(ret), K(type2), K(j_path_text));
} else if (OB_FAIL(j_base->seek(*j_path, j_path->path_node_cnt(), true, true, hit))) {
} else if (OB_FAIL(j_base->seek(*j_path, j_path->path_node_cnt(), true, false, hit))) {
LOG_WARN("fail to seek json node", K(ret), K(j_path_text));
} else if (hit.size() != 1) { // not found node by path, display "NULL"
} else if (hit.size() == 0) { // not found node by path, display "NULL"
is_null = true;
} else if (hit.size() > 1) {
res_len = hit.size();
} else {
res_len = hit[0]->member_count();
}

View File

@ -54,14 +54,19 @@ int ObExprJsonRemove::calc_result_typeN(ObExprResType& type,
return ret;
}
static int remove_from_json(ObJsonPath *path_node, ObIJsonBase *parent)
static int remove_from_json(ObJsonPath *path_node, ObIJsonBase *child)
{
INIT_SUCC(ret);
// remove item in hits
ObJsonPathBasicNode* last_node = path_node->last_path_node();
// get node to be removed
ObJsonNodeType type = parent->json_type();
if (type == ObJsonNodeType::J_OBJECT && last_node->get_node_type() == JPN_MEMBER) {
ObJsonNodeType type;
ObIJsonBase* parent = nullptr;
if (OB_FAIL(child->get_parent(parent)) || OB_ISNULL(parent)) {
// may be null parent
ret = OB_SUCCESS;
} else if (FALSE_IT(type = parent->json_type())) {
} else if (type == ObJsonNodeType::J_OBJECT && last_node->get_node_type() == JPN_MEMBER) {
ObPathMember member = last_node->get_object();
ObString key(member.len_, member.object_name_);
if (OB_FAIL(parent->object_remove(key))) {
@ -120,7 +125,7 @@ int ObExprJsonRemove::eval_json_remove(const ObExpr &expr, ObEvalCtx &ctx, ObDat
} else if (json_path->path_node_cnt() == 0) {
ret = OB_ERR_JSON_VACUOUS_PATH;
LOG_USER_ERROR(OB_ERR_JSON_VACUOUS_PATH);
} else if (OB_FAIL(json_doc->seek(*json_path, json_path->path_node_cnt() - 1, true, false, hits))) {
} else if (OB_FAIL(json_doc->seek(*json_path, json_path->path_node_cnt(), true, false, hits))) {
LOG_WARN("json seek failed", K(path_data->get_string()), K(ret));
} else if (hits.size() == 0){
continue;

View File

@ -229,9 +229,7 @@ int ObExprJsonSearch::calc_result_typeN(ObExprResType& type,
for (int64_t i = 1; OB_SUCC(ret) && i < param_num; i++) {
if (types_stack[i].get_type() == ObNullType) {
} else if (ob_is_string_type(types_stack[i].get_type())) {
if (types_stack[i].get_charset_type() != CHARSET_UTF8MB4) {
types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN);
}
types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN);
} else {
types_stack[i].set_calc_type(ObLongTextType);
types_stack[i].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN);
@ -271,11 +269,19 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat
} else if (val_type == ObNullType || json_datum->is_null()) {
is_null = true;
} else if (!ob_is_string_type(val_type)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("input type error", K(val_type));
} else {
ObString target_str = json_datum->get_string();
if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(json_arg, ctx, temp_allocator, target_str, is_null))) {
LOG_WARN("fail to get real data.", K(ret), K(target_str));
} else if (json_arg->datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN &&
OB_FAIL(ObJsonExprHelper::convert_string_collation_type(json_arg->datum_meta_.cs_type_,
CS_TYPE_UTF8MB4_BIN,
&temp_allocator,
target_str,
target_str))) {
LOG_WARN("fail to convert string", K(ret));
} else if (0 == target_str.case_compare("one")) {
one_flag = true;
} else if (0 == target_str.case_compare("all")) {
@ -297,12 +303,20 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat
} else if (val_type == ObNullType || json_datum->is_null()) {
// do nothing, null type use default escape
} else if (!ob_is_string_type(val_type)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("input type error", K(val_type));
} else {
ObString escape = json_datum->get_string();
bool is_null_str = false;
if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(json_arg, ctx, temp_allocator, escape, is_null_str))) {
LOG_WARN("fail to get real data.", K(ret), K(escape));
} else if (json_arg->datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN &&
OB_FAIL(ObJsonExprHelper::convert_string_collation_type(json_arg->datum_meta_.cs_type_,
CS_TYPE_UTF8MB4_BIN,
&temp_allocator,
escape,
escape))) {
LOG_WARN("fail to convert string", K(ret));
} else if (escape.length() > 0) {
const ObCollationType escape_coll = json_arg->datum_meta_.cs_type_;
size_t length = ObCharset::strlen_char(escape_coll, escape.ptr(), escape.length());
@ -328,12 +342,17 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat
} else if (val_type == ObNullType || json_datum->is_null()) {
is_null = true;
} else if (!ob_is_string_type(val_type)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("input type error", K(val_type));
} else {
target = json_datum->get_string();
if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(json_arg, ctx, temp_allocator, target, is_null))) {
LOG_WARN("fail to get real data.", K(ret), K(target));
}
} else if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(json_arg, ctx, temp_allocator, target, is_null))) {
LOG_WARN("fail to get real data.", K(ret), K(target));
} else if (json_arg->datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN &&
OB_FAIL(ObJsonExprHelper::convert_string_collation_type(json_arg->datum_meta_.cs_type_,
CS_TYPE_UTF8MB4_BIN,
&temp_allocator,
target,
target))) {
LOG_WARN("fail to convert string", K(ret));
}
}
@ -364,6 +383,7 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat
} else if (val_type == ObNullType || json_datum->is_null()) {
is_null = true;
} else if (!ob_is_string_type(val_type)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("input type error", K(val_type));
} else {
ObString j_path_text = json_datum->get_string();
@ -372,6 +392,13 @@ int ObExprJsonSearch::eval_json_search(const ObExpr &expr, ObEvalCtx &ctx, ObDat
LOG_WARN("fail to get real data.", K(ret), K(j_path_text));
} else if (j_path_text.length() == 0) {
is_null = true;
} else if (json_arg->datum_meta_.cs_type_ != CS_TYPE_UTF8MB4_BIN &&
OB_FAIL(ObJsonExprHelper::convert_string_collation_type(json_arg->datum_meta_.cs_type_,
CS_TYPE_UTF8MB4_BIN,
&temp_allocator,
j_path_text,
j_path_text))) {
LOG_WARN("fail to convert string", K(ret));
} else if (OB_FAIL(ObJsonExprHelper::find_and_add_cache(path_cache, j_path,
j_path_text, i, true))) {
LOG_WARN("parse text to path failed", K(j_path_text), K(ret));

View File

@ -131,6 +131,8 @@ int ObExprJsonValid::eval_json_valid(const ObExpr &expr, ObEvalCtx &ctx, ObDatum
if (OB_FAIL(arg->eval(ctx, datum))) {
LOG_WARN("eval json arg failed", K(ret));
res.set_int(0);
ret = OB_SUCCESS;
} else {
ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx);
common::ObIAllocator &tmp_allocator = tmp_alloc_g.get_allocator();