diff --git a/src/share/ob_errno.def b/src/share/ob_errno.def index 2a6db427d2..352027812b 100644 --- a/src/share/ob_errno.def +++ b/src/share/ob_errno.def @@ -1102,7 +1102,6 @@ DEFINE_PLS_ERROR_EXT(OB_ERR_INVALID_ARGUMENT_FOR_JSON_CALL, -5488, -1, "HY000", DEFINE_ERROR(OB_ERR_SCHEMA_HISTORY_EMPTY, -5489, -1, "HY000", "Schema history is empty"); DEFINE_ORACLE_ERROR(OB_ERR_TABLE_NAME_NOT_IN_LIST, -5490, -1, "42000", "table name not in FROM list", 964, "table name not in FROM list")); - DEFINE_ERROR_EXT(OB_ERR_SP_ALREADY_EXISTS, -5541, ER_SP_ALREADY_EXISTS, "42000", "procedure/function already exists", "%s %.*s already exists"); DEFINE_ERROR_EXT(OB_ERR_SP_DOES_NOT_EXIST, -5542, ER_SP_DOES_NOT_EXIST, "42000", "procedure/function does not exist", "%s %.*s.%.*s does not exist"); DEFINE_PLS_ERROR_EXT(OB_ERR_SP_UNDECLARED_VAR, -5543, ER_SP_UNDECLARED_VAR, "42000", "Undeclared variable", "Undeclared variable: %.*s", 201, "identifier must be declared", "identifier '%.*s' must be declared"); diff --git a/src/sql/engine/basic/ob_json_table_op.cpp b/src/sql/engine/basic/ob_json_table_op.cpp index 8fd3694df7..2c7ed421b4 100644 --- a/src/sql/engine/basic/ob_json_table_op.cpp +++ b/src/sql/engine/basic/ob_json_table_op.cpp @@ -1397,8 +1397,8 @@ int JtColNode::set_val_on_empty(JtScanCtx* ctx, bool& need_cast_res) break; } case JSN_QUERY_EMPTY: { - iter_ = curr_ = nullptr; - is_null_result_ = true; + iter_ = curr_ = ObJsonTableOp::get_js_array(); + is_null_result_ = false; break; } case JSN_QUERY_EMPTY_ARRAY: { diff --git a/src/sql/engine/expr/ob_expr_json_merge_patch.cpp b/src/sql/engine/expr/ob_expr_json_merge_patch.cpp index 41379da91f..de219c7e0c 100644 --- a/src/sql/engine/expr/ob_expr_json_merge_patch.cpp +++ b/src/sql/engine/expr/ob_expr_json_merge_patch.cpp @@ -196,12 +196,10 @@ int ObExprJsonMergePatch::eval_ora_json_merge_patch(const ObExpr &expr, ObEvalCt ObObjType val_type = opt_expr->datum_meta_.type_; ObCollationType cs_type = opt_expr->datum_meta_.cs_type_; if (OB_UNLIKELY(OB_FAIL(opt_expr->eval(ctx, opt_datum)))) { - SET_COVER_ERROR(ret); LOG_WARN("eval json arg failed", K(ret)); } else if (val_type == ObNullType || opt_datum->is_null()) { } else if (!ob_is_integer_type(val_type)) { ret = OB_ERR_INVALID_TYPE_FOR_OP; - SET_COVER_ERROR(ret); LOG_WARN("input type error", K(val_type)); } else { opt_array[i-2] = opt_datum->get_int(); @@ -221,10 +219,7 @@ int ObExprJsonMergePatch::eval_ora_json_merge_patch(const ObExpr &expr, ObEvalCt } else if (return_type == 0) { dst_type = expr.args_[0]->datum_meta_.type_; const ObAccuracy &default_accuracy = ObAccuracy::DDL_DEFAULT_ACCURACY[dst_type]; - dst_len = expr.args_[0]->max_length_ > 0 ? expr.args_[0]->max_length_ : default_accuracy.get_length(); - if (dst_len == 0 && dst_type == ObVarcharType) { - dst_len = OB_MAX_ORACLE_VARCHAR_LENGTH; - } + dst_len = dst_type == ObVarcharType ? OB_MAX_ORACLE_VARCHAR_LENGTH : default_accuracy.get_length(); } else if (OB_FAIL(ObJsonExprHelper::eval_and_check_res_type(return_type, dst_type, dst_len))) { LOG_WARN("fail to check returning type", K(ret)); } else if ((expr.datum_meta_.cs_type_ == CS_TYPE_BINARY || dst_type == ObJsonType) && (opt_array[OPT_PRETTY_ID] > 0 || opt_array[OPT_ASCII_ID] > 0)) { @@ -245,12 +240,13 @@ int ObExprJsonMergePatch::eval_ora_json_merge_patch(const ObExpr &expr, ObEvalCt } ObIJsonBase *j_patch_node = NULL; - if (OB_FAIL(ret) || has_null) { + int tmp_ret = OB_SUCCESS; + if ((!is_cover_error && OB_FAIL(ret)) || has_null) { // do nothing - } else if (OB_FAIL(ObJsonExprHelper::get_json_doc(expr, ctx, temp_allocator, 1, j_patch_node, has_null, true, false))) { - if (ret == OB_ERR_JSON_SYNTAX_ERROR) { + } else if ((tmp_ret = ObJsonExprHelper::get_json_doc(expr, ctx, temp_allocator, 1, j_patch_node, has_null, true, false)) != OB_SUCCESS) { + if (tmp_ret == OB_ERR_JSON_SYNTAX_ERROR) { ret = OB_ERR_JSON_PATCH_INVALID; - LOG_USER_ERROR(OB_ERR_JSON_PATCH_INVALID); + is_cover_error = false; } LOG_WARN("get_json_doc failed", K(ret)); } else if (has_null) { diff --git a/src/sql/ob_dml_stmt_printer.cpp b/src/sql/ob_dml_stmt_printer.cpp index d407d215c5..6b38be1f00 100644 --- a/src/sql/ob_dml_stmt_printer.cpp +++ b/src/sql/ob_dml_stmt_printer.cpp @@ -663,7 +663,12 @@ int ObDMLStmtPrinter::print_json_table_nested_column(const TableItem *table_item if (i > 0) { DATA_PRINTF(", "); } - DATA_PRINTF("%.*s ", LEN_AND_PTR(col_info.col_name_)); + if (col_info.is_name_quoted_) { + DATA_PRINTF("\"%.*s\" ", LEN_AND_PTR(col_info.col_name_)); + } else { + DATA_PRINTF("%.*s ", LEN_AND_PTR(col_info.col_name_)); + } + if (OB_FAIL(ret)) { } else if (col_info.col_type_ == static_cast(COL_TYPE_ORDINALITY)) { DATA_PRINTF(" for ordinality"); diff --git a/src/sql/parser/non_reserved_keywords_oracle_mode.c b/src/sql/parser/non_reserved_keywords_oracle_mode.c index 76cc1adf20..6aa7b9de31 100644 --- a/src/sql/parser/non_reserved_keywords_oracle_mode.c +++ b/src/sql/parser/non_reserved_keywords_oracle_mode.c @@ -362,6 +362,7 @@ static const NonReservedKeyword Oracle_non_reserved_keywords[] = {"approx_count_distinct_synopsis_merge", APPROX_COUNT_DISTINCT_SYNOPSIS_MERGE}, {"ascii", ASCII}, {"asensitive", ASENSITIVE}, + {"asis", ASIS}, {"at", AT}, {"authors", AUTHORS}, {"auto", AUTO}, diff --git a/src/sql/parser/parse_node.h b/src/sql/parser/parse_node.h index ab5ae19088..1d19f06f98 100644 --- a/src/sql/parser/parse_node.h +++ b/src/sql/parser/parse_node.h @@ -144,7 +144,7 @@ typedef struct _ParseNode uint32_t is_empty_ : 1; // 表示是否缺省该节点,1表示缺省,0表示没有缺省, opt_asc_desc节点中使用到 uint32_t is_multiset_ : 1; // for cast(multiset(...) as ...) uint32_t is_forbid_anony_parameter_ : 1; // 1 表示禁止匿名块参数化 - uint32_t is_input_quoted : 1; // indicate name_ob input whether with double quote + uint32_t is_input_quoted_ : 1; // indicate name_ob input whether with double quote uint32_t reserved_; }; }; diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index 8b82b39af0..c826104431 100755 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -616,7 +616,7 @@ int ObDMLResolver::print_json_path(ParseNode *&tmp_path, ObJsonBuffer &res_str) } else { if (OB_FAIL(res_str.append("."))) { LOG_WARN("dot symbol write fail", K(ret)); - } else if (tmp_path->children_[0]->is_input_quoted == 1 && OB_FAIL(res_str.append("\""))) { + } else if (tmp_path->children_[0]->is_input_quoted_ == 1 && OB_FAIL(res_str.append("\""))) { LOG_WARN("add \" fail in side", K(ret)); } else if (OB_NOT_NULL(tmp_path->children_[0]->raw_text_) && OB_FAIL(res_str.append(tmp_path->children_[0]->raw_text_, tmp_path->children_[0]->text_len_))) { @@ -625,7 +625,7 @@ int ObDMLResolver::print_json_path(ParseNode *&tmp_path, ObJsonBuffer &res_str) if (OB_FAIL(res_str.append(tmp_path->children_[0]->str_value_, tmp_path->children_[0]->str_len_))) { LOG_WARN("str_value write fail"); } - } else if (tmp_path->children_[0]->is_input_quoted == 1 && OB_FAIL(res_str.append("\""))) { + } else if (tmp_path->children_[0]->is_input_quoted_ == 1 && OB_FAIL(res_str.append("\""))) { LOG_WARN("add \" fail in side", K(ret)); } if (tmp_path->type_ == T_FUN_SYS) { @@ -7654,15 +7654,58 @@ int ObDMLResolver::json_table_make_json_path(const ParseNode &parse_tree, if (OB_ISNULL(allocator)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("allocator is NULL", K(ret)); + } else if (parse_tree.type_ == T_OBJ_ACCESS_REF) { + ObJsonBuffer path_buffer(allocator); + if (OB_FAIL(path_buffer.append("$."))) { + LOG_WARN("failed to append path start", K(ret)); + } else if (parse_tree.num_child_ != 2 + || OB_ISNULL(parse_tree.children_) + || OB_ISNULL(parse_tree.children_[0]) + || OB_ISNULL(parse_tree.children_[1])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to make path, param not expected", K(ret), K(parse_tree.num_child_), + KP(parse_tree.children_)); + } else if (OB_FAIL(path_buffer.append(parse_tree.children_[0]->str_value_, + parse_tree.children_[0]->str_len_))) { + LOG_WARN("failed to append raw text", K(ret)); + } else { + ParseNode *tmp_path = parse_tree.children_[1]; + while (OB_SUCC(ret) && OB_NOT_NULL(tmp_path)) { + if (OB_ISNULL(tmp_path->children_[0])) { + tmp_path = NULL; + // do nothing + } else { + if (OB_FAIL(print_json_path(tmp_path, path_buffer))) { + LOG_WARN("failed to print path", K(ret)); + } + } + } + + char* path_buf = NULL; + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(path_buf = static_cast(allocator->alloc(path_buffer.length() + 1)))) { + LOG_WARN("failed to allocate path buffer", K(ret), K(path_buffer.length())); + } else { + MEMCPY(path_buf, path_buffer.ptr(), path_buffer.length()); + path_buf[path_buffer.length()] = 0; + path_str.assign_ptr(path_buf, strlen(path_buf)); + } + } } else { - char* str_buf = static_cast(allocator->alloc(parse_tree.str_len_ + 3)); + char* str_buf = static_cast(allocator->alloc(parse_tree.text_len_ + 3)); if (OB_ISNULL(str_buf)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory failed", K(ret), K(parse_tree.str_len_)); } else { - MEMCPY(str_buf + 2, parse_tree.raw_text_, parse_tree.text_len_); MEMCPY(str_buf, "$.", 2); - str_buf[parse_tree.str_len_ + 2] = '\0'; + str_buf[parse_tree.text_len_ + 2] = '\0'; + if (parse_tree.text_len_ > 0 + && (parse_tree.raw_text_[0] == '\'' && parse_tree.raw_text_[parse_tree.text_len_-1] == '\'')) { + MEMCPY(str_buf + 2, parse_tree.raw_text_ + 1, parse_tree.text_len_ - 1); + str_buf[parse_tree.text_len_] = '\0'; + } else { + MEMCPY(str_buf + 2, parse_tree.raw_text_, parse_tree.text_len_); + } path_str.assign_ptr(str_buf, strlen(str_buf)); } } @@ -7687,13 +7730,21 @@ int ObDMLResolver::resolve_json_table_column_name_and_path(const ParseNode *name } else if (path_node->type_ != T_NULL && (path_node->str_len_ > 0 && OB_NOT_NULL(path_node->str_value_))) { col_def->col_base_info_.path_.assign_ptr(path_node->str_value_, path_node->str_len_); + if (*path_node->str_value_ != '$' && path_node->value_ != 1 + && OB_FAIL(json_table_make_json_path(*path_node, allocator, col_def->col_base_info_.path_))) { + LOG_WARN("failed to make json path", K(ret)); + } } else if (path_node->type_ == T_NULL - && OB_FAIL(json_table_make_json_path(*name_node, allocator, col_def->col_base_info_.path_))) { - LOG_WARN("failed to make json path", K(ret)); + && OB_FAIL(json_table_make_json_path(*name_node, allocator, col_def->col_base_info_.path_))) { + LOG_WARN("failed to make json path by name", K(ret)); + } else if (path_node->type_ == T_OBJ_ACCESS_REF + && OB_FAIL(json_table_make_json_path(*path_node, allocator, col_def->col_base_info_.path_))) { + LOG_WARN("failed to make json path by lists", K(ret)); } if (OB_SUCC(ret)) { col_def->col_base_info_.col_name_.assign_ptr(name_node->str_value_, name_node->str_len_); + col_def->col_base_info_.is_name_quoted_ = name_node->is_input_quoted_; } return ret; } @@ -7784,6 +7835,7 @@ int ObDMLResolver::resolve_json_table_column_type(const ParseNode &parse_tree, if (ObNumberType == obj_type && parse_tree.int16_values_[2] == -1) { accuracy.set_precision(parse_tree.int16_values_[2]); accuracy.set_scale(parse_tree.int16_values_[3]); + } else if (ObIntType == obj_type) { } else { accuracy.set_precision(parse_tree.int16_values_[2]); accuracy.set_scale(parse_tree.int16_values_[3]); diff --git a/src/sql/resolver/dml/ob_dml_stmt.cpp b/src/sql/resolver/dml/ob_dml_stmt.cpp index 87fb2720d1..ea80c748e5 100644 --- a/src/sql/resolver/dml/ob_dml_stmt.cpp +++ b/src/sql/resolver/dml/ob_dml_stmt.cpp @@ -4525,7 +4525,8 @@ ObJtColBaseInfo::ObJtColBaseInfo() res_type_(-1), data_type_(), parent_id_(-1), - id_(-1) {} + id_(-1), + value_(0) {} ObJtColBaseInfo::ObJtColBaseInfo(const ObJtColBaseInfo& info) : col_type_(info.col_type_), @@ -4545,7 +4546,8 @@ ObJtColBaseInfo::ObJtColBaseInfo(const ObJtColBaseInfo& info) res_type_(info.res_type_), data_type_(info.data_type_), parent_id_(info.parent_id_), - id_(info.id_) {} + id_(info.id_), + value_(info.value_) {} int ObJtColBaseInfo::deep_copy(const ObJtColBaseInfo& src, ObIAllocator* allocator) { @@ -4581,6 +4583,7 @@ int ObJtColBaseInfo::deep_copy(const ObJtColBaseInfo& src, ObIAllocator* allocat data_type_ = src.data_type_; parent_id_ = src.parent_id_; id_ = src.id_; + value_ = src.value_; } return ret; } @@ -4607,6 +4610,7 @@ int ObJtColBaseInfo::assign(const ObJtColBaseInfo& src) data_type_ = src.data_type_; parent_id_ = src.parent_id_; id_ = src.id_; + value_ = src.value_; return ret; } diff --git a/src/sql/resolver/dml/ob_dml_stmt.h b/src/sql/resolver/dml/ob_dml_stmt.h index 6474129332..5e1dfa8264 100644 --- a/src/sql/resolver/dml/ob_dml_stmt.h +++ b/src/sql/resolver/dml/ob_dml_stmt.h @@ -459,6 +459,13 @@ typedef struct ObJtColBaseInfo ObDataType data_type_; int32_t parent_id_; int32_t id_; + union { + int32_t value_; + struct { + int32_t is_name_quoted_ : 1; + int32_t reserved_ : 31; + }; + }; int deep_copy(const ObJtColBaseInfo& src, ObIAllocator* allocator); int assign(const ObJtColBaseInfo& src);