fix:json-remove, json is true/false, json-length bug
This commit is contained in:
@ -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[] = {
|
||||
|
||||
@ -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)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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();
|
||||
|
||||
Reference in New Issue
Block a user