bugfix : json object resolve column expr cause core-dump

This commit is contained in:
obdev 2023-03-24 10:48:57 +00:00 committed by ob-robot
parent cb1ec965d4
commit 607b78760e
2 changed files with 103 additions and 160 deletions

View File

@ -4954,7 +4954,7 @@ int ObRawExprResolverImpl::malloc_new_specified_type_node(common::ObIAllocator &
return ret;
}
// use: json value (mismatch ype) ; json object (entry_op)
// use: json value (mismatch ype)
int ObRawExprResolverImpl::expand_node(common::ObIAllocator &allocator, ParseNode *node, int p, ObVector<const ParseNode*> &arr) {
int ret = OB_SUCCESS;
if (node->type_ == T_LINK_NODE || node->type_ == T_VALUE_VECTOR)
@ -4962,149 +4962,11 @@ int ObRawExprResolverImpl::expand_node(common::ObIAllocator &allocator, ParseNod
for (int32_t i = 0; OB_SUCC(ret) && i < node->num_child_; i++){
if (OB_ISNULL(node->children_[i])) {
} else {
ObString rownum_str(6, "rownum");
if (lib::is_oracle_mode() && ctx_.current_scope_ == T_FIELD_LIST_SCOPE && node->children_[i]->type_ == T_FUN_SYS
&& node->children_[i]->num_child_ == 1 && OB_NOT_NULL(node->children_[i]->children_[0])
&& node->children_[i]->children_[0]->type_ == T_IDENT
&& 0 == rownum_str.case_compare(node->children_[i]->children_[0]->str_value_)
&& i % 3 == 0 && node->children_[i + 1]->type_ == T_NULL
&& node->children_[i + 1]->value_ == 2) {
ParseNode *fun_key_node;
if (OB_ISNULL(fun_key_node = static_cast<ParseNode*>(allocator.alloc(sizeof(ParseNode))))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to allocate memory", K(ret), K(sizeof(ParseNode)));
} else {
fun_key_node = new(fun_key_node) ParseNode;
if (OB_ISNULL(node->children_[i]->children_[0])) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("no legeal fun", K(ret));
} else {
ObString str_fun(node->children_[i]->children_[0]->str_len_, node->children_[i]->children_[0]->str_value_);
if (OB_FAIL(ObRawExprResolverImpl::malloc_new_specified_type_node(allocator, str_fun, fun_key_node, T_CHAR))) {
LOG_WARN("key node create fail", K(ret));
} else {
node->children_[i + 1] = node->children_[i];
node->children_[i] = fun_key_node;
}
}
}
} else if (node->children_[i]->type_ == T_OBJ_ACCESS_REF
&& i % 3 == 0 && node->children_[i+1]->type_ == T_NULL && node->children_[i+1]->value_ == 2) {
ParseNode *column_ref_node;
ParseNode *t_node = node->children_[i];
ParseNode *pre_node = NULL;
bool is_fun_sys = false;
if (OB_ISNULL(column_ref_node = static_cast<ParseNode*>(allocator.alloc(sizeof(ParseNode))))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to allocate memory", K(ret), K(sizeof(ParseNode)));
} else {
column_ref_node = new(column_ref_node) ParseNode;
if (OB_FAIL(ObRawExprResolverImpl::malloc_new_specified_type_node(allocator, "", column_ref_node, T_OBJ_ACCESS_REF))) {
LOG_WARN("key node create fail", K(ret));
} else {
node->children_[i]->value_ = 1;
pre_node = column_ref_node;
}
}
while (OB_SUCC(ret) && !is_fun_sys && t_node != NULL && t_node->type_ == T_OBJ_ACCESS_REF) {
if (OB_ISNULL(t_node->children_[0]) || t_node->children_[0]->type_ != T_IDENT) {
is_fun_sys = true;
} else {
ParseNode *col_ref_node = NULL;
ParseNode *ident_node = NULL;
if (OB_ISNULL(ident_node = static_cast<ParseNode*>(allocator.alloc(sizeof(ParseNode))))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to allocate memory", K(ret), K(sizeof(ParseNode)));
} else {
ident_node = new(ident_node) ParseNode;
memset(ident_node, 0, sizeof(ParseNode));
ident_node->type_ = T_IDENT;
ident_node->str_value_ = t_node->children_[0]->str_value_;
ident_node->str_len_ = t_node->children_[0]->str_len_;
ident_node->raw_text_ = t_node->children_[0]->raw_text_;
ident_node->text_len_ = t_node->children_[0]->text_len_;
pre_node->children_[0] = ident_node;
}
if (OB_FAIL(ret) || OB_ISNULL(t_node->children_[1])) {
} else if (OB_ISNULL(col_ref_node = static_cast<ParseNode*>(allocator.alloc(sizeof(ParseNode))))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to allocate memory", K(ret), K(sizeof(ParseNode)));
} else {
col_ref_node = new(col_ref_node) ParseNode;
if (OB_FAIL(ObRawExprResolverImpl::malloc_new_specified_type_node(allocator, "", col_ref_node, T_OBJ_ACCESS_REF))) {
LOG_WARN("key node create fail", K(ret));
} else {
pre_node->children_[1] = col_ref_node;
}
}
if (OB_SUCC(ret)) {
pre_node = col_ref_node;
}
t_node = t_node->children_[1];
}
}
if (OB_SUCC(ret) && !is_fun_sys && OB_ISNULL(node->children_[i+1] = column_ref_node)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("column_node copy failed", K(ret));
}
}
if (OB_SUCC(ret) && OB_FAIL(SMART_CALL(expand_node(allocator, node->children_[i], i, arr)))) {
LOG_WARN("node expand fail", K(ret));
}
}
}
} else if (node->type_ == T_STAR) {
// do nothing
} else if ((node->type_ == T_COLUMN_REF || node->type_ == T_OBJ_ACCESS_REF) && node->value_ == 1 && p % 3 == 0) {
ObQualifiedName column_ref;
ParseNode *col_node;
if (nullptr == (col_node = static_cast<ParseNode*>(allocator.alloc(sizeof(ParseNode))))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to allocate memory", K(ret), K(sizeof(ParseNode)));
} else if (node->type_ == T_COLUMN_REF) {
if (OB_FAIL(ObResolverUtils::resolve_column_ref(
node, ctx_.case_mode_, column_ref))) {
LOG_WARN("fail to resolve column ref", K(ret));
}
if (OB_NOT_NULL(node->children_[2]->raw_text_)) {
column_ref.col_name_ = node->children_[2]->raw_text_;
}
} else if (node->type_ == T_OBJ_ACCESS_REF) {
while (node->children_[1] != NULL) {
node = node->children_[1];
}
if (OB_NOT_NULL(node->children_[0]) && node->children_[0]->type_ == T_IDENT) {
if (OB_FAIL(ObResolverUtils::resolve_obj_access_ref_node(
ctx_.expr_factory_, node->children_[0], column_ref, *ctx_.session_info_))) {
LOG_WARN("fail to resolve column ref", K(ret));
}
if (OB_NOT_NULL(node->children_[0]->raw_text_)) {
column_ref.col_name_ = node->children_[0]->raw_text_;
}
} else {
column_ref.is_star_ = true;
const ParseNode* new_node = node;
if (OB_FAIL(arr.push_back(node))) {
LOG_WARN("node resolver fail", K(ret));
}
}
}
if (OB_SUCC(ret) && !column_ref.is_star_) {
col_node = new(col_node) ParseNode;
ObString col_name = column_ref.col_name_;
if (OB_FAIL(ObRawExprResolverImpl::malloc_new_specified_type_node(allocator, col_name, col_node, T_CHAR))) {
LOG_WARN("fail to create column node ");
}
const ParseNode* new_node = col_node;
if (OB_FAIL(arr.push_back(new_node))) {
LOG_WARN("node resolver fail", K(ret));
}
}
} else if (node->type_ == T_COLUMN_REF && node->children_[2]->type_ == T_STAR) {
// do nothing
} else if (node->type_ == T_NULL && node->value_ == 2) {
// do nothing
} else {
const ParseNode* new_node = node;
if (OB_FAIL(arr.push_back(node))) {
@ -5162,9 +5024,38 @@ int ObRawExprResolverImpl::remove_strict_opt_in_pl(ParseNode *node, int8_t expr_
return ret;
}
int ObRawExprResolverImpl::get_column_raw_text_from_node(const ParseNode *node, ObString &col_name)
{
INIT_SUCC(ret);
ObQualifiedName column_ref;
if (node->type_ == T_COLUMN_REF) {
col_name = node->children_[2]->raw_text_;
} else if (node->type_ == T_OBJ_ACCESS_REF) {
while (OB_SUCC(ret) && node->children_[1] != NULL) {
node = node->children_[1];
if (node->type_ != T_OBJ_ACCESS_REF) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to get column name from node", K(ret));
}
}
if (OB_SUCC(ret) && OB_NOT_NULL(node->children_[0]) && node->children_[0]->type_ == T_IDENT) {
col_name = node->children_[0]->raw_text_;
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to get column name from node", K(ret));
}
}
return ret;
}
int ObRawExprResolverImpl::process_ora_json_object_node(const ParseNode *node, ObRawExpr *&expr)
{
INIT_SUCC(ret);
ObVector<const ParseNode*> key_value_arr;
ParseNode* data_node = NULL;
ParseNode* cur_node_kv = NULL;
int cur_col_size = 0;
ParseNode key_node;
CK(OB_NOT_NULL(node));
int32_t num = 0;
if (OB_SUCC(ret)) {
@ -5208,7 +5099,6 @@ int ObRawExprResolverImpl::process_ora_json_object_node(const ParseNode *node, O
}
}
ObVector<const ParseNode*> key_value_arr;
if (OB_SUCC(ret)) {
const ParseNode *key_value = node->children_[0];
if (OB_ISNULL(key_value)) {
@ -5226,30 +5116,76 @@ int ObRawExprResolverImpl::process_ora_json_object_node(const ParseNode *node, O
LOG_WARN("illegal use of 'strcit' clause.");
}
}
ParseNode *cur_node = NULL;
if (OB_FAIL(ret) || OB_ISNULL(key_value)) {
} else if (OB_NOT_NULL(node->children_[0]) && (node->children_[0]->num_child_ == 0 || (node->children_[0]->num_child_ > 0 && OB_ISNULL(cur_node = node->children_[0]->children_[0])))) {
} else if (cur_node->type_ == T_COLUMN_REF && OB_NOT_NULL(cur_node->children_[2]) && cur_node->children_[2]->type_ == T_STAR) {
} else if (OB_FAIL(expand_node(ctx_.local_allocator_, const_cast<ParseNode *>(key_value), 0, key_value_arr))) {
LOG_WARN("expand node has error", K(ret), K(key_value_arr.size()));
} else if (key_value_arr.size() != key_value->num_child_) {
ret = OB_ERR_MISS_VALUE;
LOG_WARN("missing value keyword", K(ret), K(key_value_arr.size()), K(key_value->num_child_));
}
if (OB_SUCC(ret)) {
// [key-value(vector)][null_type][returning_type][strict][unique_keys]
for (int32_t i = 0; OB_SUCC(ret) && i < key_value_arr.size(); i++) {
if (key_value_arr[i]->type_ == T_LINK_NODE || key_value_arr[i]->type_ == T_VALUE_VECTOR) {
} else {
// [key-value(vector)]
if (OB_NOT_NULL(node->children_[0])) {
data_node = node->children_[0];
for (int64_t i = 0; OB_SUCC(ret) && i < data_node->num_child_; i++) { // 3 node in group
ObRawExpr *para_expr = NULL;
CK(OB_NOT_NULL(key_value_arr[i]));
OZ(SMART_CALL(recursive_resolve(key_value_arr[i], para_expr)));
CK(OB_NOT_NULL(para_expr));
OZ(func_expr->add_param_expr(para_expr));
cur_node_kv = NULL;
int val_pos = i + 1; // key is i where i % 3 == 0 , value is i + 1, format json is i + 2
if (OB_ISNULL(data_node->children_[i])) {
} else if ((i % 3 == 1) && data_node->children_[i]->type_ == T_NULL && data_node->children_[i]->value_ == 2) { // 2 is flag of empty value
cur_node_kv = data_node->children_[i - 1];
} else {
cur_node_kv = data_node->children_[i];
}
if (OB_FAIL(ret) || OB_ISNULL(cur_node_kv)) {
} else if (OB_FAIL(SMART_CALL(recursive_resolve(cur_node_kv, para_expr)))) {
LOG_WARN("fail to get raw expr from node", K(ret), K(i));
} else if (OB_ISNULL(para_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("raw expr is null", K(ret), K(i));
} else if ((i % JSON_OBJECT_GROUP == ObJsonObjectEntry::JSON_OBJECT_KEY) && data_node->children_[val_pos]->type_ == T_NULL
&& data_node->children_[val_pos]->value_ == 2 // 2 is flag of empty value
&& !(((para_expr->get_expr_type() == T_COLUMN_REF // column type
|| para_expr->get_expr_type() == T_REF_COLUMN)
&& ctx_.columns_->at(ctx_.columns_->count()-1).access_idents_.at(0).get_type() == oceanbase::sql::UNKNOWN)
|| para_expr->get_expr_type() == T_FUN_SYS_ROWNUM)) { // rownum
ret = OB_ERR_MISS_VALUE;
LOG_WARN("missing value keyword", K(ret), K(para_expr->get_expr_type()), K(i));
} else if ((i % JSON_OBJECT_GROUP == ObJsonObjectEntry::JSON_OBJECT_KEY) && data_node->children_[val_pos]->type_ == T_NULL
&& data_node->children_[val_pos]->value_ == 2 // 2 is flag of empty value
&& (((para_expr->get_expr_type() == T_COLUMN_REF // column type
|| para_expr->get_expr_type() == T_REF_COLUMN)
&& ctx_.columns_->at(ctx_.columns_->count() - 1).access_idents_.at(0).get_type() == oceanbase::sql::UNKNOWN)
|| para_expr->get_expr_type() == T_FUN_SYS_ROWNUM)) { // rownum
ObString col_name;
if (para_expr->get_expr_type() == T_FUN_SYS_ROWNUM) {
col_name.assign_ptr("rownum", 6);
} else if (ctx_.columns_->count() > cur_col_size && OB_SUCC(get_column_raw_text_from_node(cur_node_kv, col_name))) {
for (int col_pos = cur_col_size; col_pos < ctx_.columns_->count(); col_pos ++) {
ctx_.columns_->pop_back(); // delete column para
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to resolve column", K(ret), K(cur_col_size), K(ctx_.columns_->count()));
}
para_expr = NULL;
if (OB_FAIL(ret)) {
} else if (OB_FAIL(ObRawExprResolverImpl::malloc_new_specified_type_node(ctx_.local_allocator_, col_name, &key_node, T_CHAR))) {
LOG_WARN("create json doc node fail", K(ret));
} else if (OB_FAIL(SMART_CALL(recursive_resolve(&key_node, para_expr)))) {
LOG_WARN("fail to get raw expr from node", K(ret), K(i));
} else if (OB_ISNULL(para_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("raw expr is null", K(ret), K(i));
} else if (OB_FAIL(func_expr->add_param_expr(para_expr))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to add into func expr", K(ret), K(i));
} else {
cur_col_size = ctx_.columns_->count();
}
} else if (OB_FAIL(func_expr->add_param_expr(para_expr))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("fail to add into func expr", K(ret), K(i));
} else {
cur_col_size = ctx_.columns_->count();
}
}
} //end for
// ([on_mismatch][opt_mismatch_types] on oracle)
}
// [null_type][returning_type][strict][unique_keys]
for (int32_t i = 1; OB_SUCC(ret) && i < num; i++) {
ObRawExpr *para_expr = NULL;
CK(OB_NOT_NULL(node->children_[i]));

View File

@ -104,10 +104,17 @@ private:
OPT_JSON_OBJECT,
OPT_JSON_ARRAY,
};
enum ObJsonObjectEntry: int8_t {
JSON_OBJECT_KEY = 0,
JSON_OBJECT_VAL = 1,
JSON_OBJECT_FORMAT = 2
};
const int JSON_OBJECT_GROUP = 3;
int remove_strict_opt_in_pl(ParseNode *node, int8_t expr_flag);
int remove_format_json_opt_in_pl(ParseNode *node, int8_t expr_flag);
int process_json_value_node(const ParseNode *node, ObRawExpr *&expr);
int pre_check_json_path_valid(const ParseNode *node);
int get_column_raw_text_from_node(const ParseNode *node, ObString &col_name);
int process_ora_json_object_node(const ParseNode *node, ObRawExpr *&expr);
int process_is_json_node(const ParseNode *node, ObRawExpr *&expr);
int process_json_equal_node(const ParseNode *node, ObRawExpr *&expr);