diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index 9f96a2a68f..ec5e82dcc6 100755 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -298,6 +298,29 @@ int ObDMLResolver::pre_process_json_expr_constraint(ParseNode *node, common::ObI return ret; } +int ObDMLResolver::expand_column_in_json_object_star(ParseNode *node) +{ + INIT_SUCC(ret); + ObSEArray columns_list; + TableItem *table_item = NULL; + bool tab_has_alias = false; + ObString tab_name; + bool all_tab = true; + ObDMLStmt *stmt = static_cast(stmt_); + if (OB_ISNULL(node) || OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("node should not be null", K(ret)); + } else if (OB_NOT_NULL(node->children_[1])) { + tab_name.assign_ptr(node->children_[1]->str_value_, node->children_[1]->str_len_); + all_tab = false; + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(get_target_column_list(columns_list, tab_name, all_tab, tab_has_alias, table_item))) { + LOG_WARN("parse column fail"); + } + return ret; +} + int ObDMLResolver::process_json_object_array_node(ParseNode *node, common::ObIAllocator &allocator) { INIT_SUCC(ret); @@ -327,6 +350,9 @@ int ObDMLResolver::process_json_object_array_node(ParseNode *node, common::ObIAl if (OB_NOT_NULL(cur_node) && cur_node->type_ == T_COLUMN_REF && OB_NOT_NULL(cur_node->children_[2]) && cur_node->children_[2]->type_ == T_STAR) { // ignore wild card node + if (OB_FAIL(expand_column_in_json_object_star(cur_node))) { // append column item into stmt + LOG_WARN("fail to expand column item of json object star", K(ret)); + } } else { if (OB_NOT_NULL(value_node) && OB_NOT_NULL(format_node)) { bool format_json = format_node->value_; diff --git a/src/sql/resolver/dml/ob_dml_resolver.h b/src/sql/resolver/dml/ob_dml_resolver.h index 153dacce4d..80b05f24d8 100644 --- a/src/sql/resolver/dml/ob_dml_resolver.h +++ b/src/sql/resolver/dml/ob_dml_resolver.h @@ -219,6 +219,7 @@ public: bool include_hidden, ColumnItem *&col_item); // dot notation + int expand_column_in_json_object_star(ParseNode *node); int pre_process_json_expr(ParseNode &node); int print_json_path(ParseNode *&tmp_path, ObJsonBuffer &res_str); int check_depth_obj_access_ref(ParseNode *node, int8_t &depth, bool &exist_fun, ObJsonBuffer &sql_str, bool obj_check = true); // obj_check : whether need check dot notaion diff --git a/src/sql/resolver/expr/ob_raw_expr_printer.cpp b/src/sql/resolver/expr/ob_raw_expr_printer.cpp index 6fdd728bc3..ac1a265e0e 100644 --- a/src/sql/resolver/expr/ob_raw_expr_printer.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_printer.cpp @@ -1974,9 +1974,10 @@ int ObRawExprPrinter::print_json_value(ObSysFunRawExpr *expr) int ObRawExprPrinter::print_dot_notation(ObSysFunRawExpr *expr) { INIT_SUCC(ret); - PRINT_EXPR(expr->get_param_expr(0)); - // DATA_PRINTF("."); - // PRINT_EXPR(expr->get_param_expr(1)); + const ObString db_str(0, ""); + ObColumnRefRawExpr *bin_expr = static_cast(expr->get_param_expr(0)); + bin_expr->set_database_name(db_str); + PRINT_EXPR(bin_expr); // table_name.col_name not print db_name ObObj path_obj = static_cast(expr->get_param_expr(1))->get_value(); ObItemType expr_type = expr->get_param_expr(1)->get_expr_type(); if (T_VARCHAR != expr_type && T_CHAR != expr_type) { @@ -2409,10 +2410,10 @@ int ObRawExprPrinter::print_json_expr(ObSysFunRawExpr *expr) ObString func_name = expr->get_func_name(); switch (expr->get_expr_type()) { case T_FUN_SYS_JSON_VALUE: { - // if json value only have one mismatch clause, the size of parameter is 12 - const int8_t JSN_VAL_WITH_ONE_MISMATCH = 12; - // json value parameter count more than 12, because mismatch is multi-val and default value. - // json_value(expr(0), expr(1) returning cast_type ascii xxx on empty(default value) xxx on error(default value) xxx on mismatch (xxx)) + // if json value only have one mismatch clause, the size of parameter is 13 + const int8_t JSN_VAL_WITH_ONE_MISMATCH = 13; + // json value parameter count more than 13, because mismatch is multi-val and default value. + // json_value(expr(0), expr(1) returning cast_type truncate ascii xxx on empty(default value) xxx on error(default value) xxx on mismatch (xxx)) if (OB_UNLIKELY(expr->get_param_count() < JSN_VAL_WITH_ONE_MISMATCH)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected param count of expr to type", K(ret), KPC(expr)); diff --git a/src/sql/rewrite/ob_transform_utils.cpp b/src/sql/rewrite/ob_transform_utils.cpp index 98ee529651..d90918f9e7 100644 --- a/src/sql/rewrite/ob_transform_utils.cpp +++ b/src/sql/rewrite/ob_transform_utils.cpp @@ -13353,6 +13353,67 @@ int ObTransformUtils::check_is_json_constraint(ObTransformerCtx *ctx, return ret; } +int ObTransformUtils::add_dummy_expr_for_json_object_node(ObTransformerCtx *ctx, + ObSEArray& param_array) +{ + INIT_SUCC(ret); + ObConstRawExpr* key_expr = NULL; + ObConstRawExpr* value_expr = NULL; + ObConstRawExpr* format_expr = NULL; + const char *ptr_name = "DUMMY"; + const char *ptr_value = "X"; + if (OB_ISNULL(ctx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("input can not be null", K(ret)); + } else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_VARCHAR, key_expr))) { + LOG_WARN("create const expr failed", K(ret)); + } else if (OB_ISNULL(key_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("true expr is NULL", K(ret)); + } else { + ObObj key_obj; + key_obj.set_varchar(ptr_name); + key_obj.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + key_obj.set_collation_level(CS_LEVEL_IMPLICIT); + key_expr->set_value(key_obj); + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_VARCHAR, value_expr))) { + LOG_WARN("create const expr failed", K(ret)); + } else if (OB_ISNULL(key_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("true expr is NULL", K(ret)); + } else { + ObObj val_obj; + val_obj.set_varchar(ptr_value); + val_obj.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + val_obj.set_collation_level(CS_LEVEL_IMPLICIT); + value_expr->set_value(val_obj); + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_INT, format_expr))) { + LOG_WARN("create const expr failed", K(ret)); + } else if (OB_ISNULL(format_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("true expr is NULL", K(ret)); + } else { + ObObj format_obj; + format_obj.set_int(0); + format_expr->set_data_type(ObIntType); + format_expr->set_value(format_obj); + format_expr->set_param(format_obj); + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(param_array.push_back(key_expr))) { + LOG_WARN("can not push key expr to array", K(ret)); + } else if (OB_FAIL(param_array.push_back(value_expr))) { + LOG_WARN("can not push key expr to array", K(ret)); + } else if (OB_FAIL(param_array.push_back(format_expr))) { + LOG_WARN("can not push key expr to array", K(ret)); + } + return ret; +} + int ObTransformUtils::add_column_expr_for_json_object_node(ObTransformerCtx *ctx, ObDMLStmt *stmt, ColumnItem& col_item, @@ -13423,6 +13484,7 @@ int ObTransformUtils::get_expand_node_from_star(ObTransformerCtx *ctx, ObString tab_name; bool tab_has_alias = false; ObSEArray columns_list; + bool is_empty_table = false; if (OB_ISNULL(param_expr) || param_expr->get_param_count() != 1 || OB_ISNULL(param_expr->get_param_expr(TABLE_NAME_POS))) { @@ -13434,11 +13496,15 @@ int ObTransformUtils::get_expand_node_from_star(ObTransformerCtx *ctx, all_tab = false; } if (OB_FAIL(ret)) { - } else if (OB_FAIL(get_column_node_from_table(ctx, stmt, tab_name, columns_list, all_tab, tab_has_alias, table))) { + } else if (OB_FAIL(get_column_node_from_table(ctx, stmt, tab_name, columns_list, all_tab, tab_has_alias, table, is_empty_table))) { LOG_WARN("fail to get coulmn node from table", K(ret)); } else if (OB_ISNULL(table)) { - ret = OB_ERR_KEY_COLUMN_DOES_NOT_EXITS; - LOG_USER_ERROR(OB_ERR_KEY_COLUMN_DOES_NOT_EXITS, tab_name.length(), tab_name.ptr()); + if (!is_empty_table) { + ret = OB_ERR_KEY_COLUMN_DOES_NOT_EXITS; + LOG_USER_ERROR(OB_ERR_KEY_COLUMN_DOES_NOT_EXITS, tab_name.length(), tab_name.ptr()); + } else if (OB_FAIL(add_dummy_expr_for_json_object_node(ctx, param_array))) { + LOG_WARN("fail to resolve dual table", K(ret)); + } } else { int64_t num = columns_list.count(); for (int64_t i = 0; OB_SUCC(ret) && i < num; i++) { @@ -13458,13 +13524,15 @@ int ObTransformUtils::get_column_node_from_table(ObTransformerCtx *ctx, ObSEArray& column_list, bool all_tab, bool &tab_has_alias, - TableItem *&tab_item) + TableItem *&tab_item, + bool &is_empty_table) { INIT_SUCC(ret); int64_t num = 0; ObColumnRefRawExpr *col_expr = NULL; const ObTableSchema *table_schema = NULL; const ObColumnSchemaV2 *col_schema = NULL; + bool col_is_exist = false; if (OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; @@ -13472,6 +13540,9 @@ int ObTransformUtils::get_column_node_from_table(ObTransformerCtx *ctx, } else { num = stmt->get_table_size(); } + if (num == 0) { + is_empty_table = true; + } for (int64_t i = 0; OB_SUCC(ret) && i < num; i++) { const TableItem *tmp_table_item = stmt->get_table_item(i); if (OB_ISNULL(tmp_table_item)) { @@ -13505,14 +13576,19 @@ int ObTransformUtils::get_column_node_from_table(ObTransformerCtx *ctx, ObTableSchema::const_column_iterator iter = table_schema->column_begin(); ObTableSchema::const_column_iterator end = table_schema->column_end(); for (int64_t i = 0; OB_SUCC(ret) && iter != end; ++iter, i++) { + col_is_exist = false; col_schema = *iter; col_expr = NULL; ColumnItem column_item; ColumnItem* col_item = stmt->get_column_item_by_id(tmp_table_item->table_id_, col_schema->get_column_id()); if (OB_NOT_NULL(col_item)) { - } else if (OB_ISNULL(col_schema)) { + col_is_exist = true; + } else if (OB_ISNULL(col_schema) || col_schema->is_generated_column()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("column schema is NULL", K(ret)); + } else if (col_schema->is_extend()) { + ret = OB_ERR_JSON_FUN_UNSUPPORTED_TYPE; + LOG_WARN("unsupported data type in json object function", K(ret)); } else if (ObRawExprUtils::build_column_expr(*ctx->expr_factory_, *col_schema, col_expr)) { LOG_WARN("fail to create col expr by column schema", K(ret)); } else { @@ -13525,7 +13601,7 @@ int ObTransformUtils::get_column_node_from_table(ObTransformerCtx *ctx, col_item = &column_item; } if (OB_FAIL(ret)) { - } else if (OB_FAIL(stmt->add_column_item(*col_item))) { + } else if (!col_is_exist && OB_FAIL(stmt->add_column_item(*col_item))) { LOG_WARN("add column item to stmt failed", K(ret), K(col_item)); } else if (OB_FAIL(column_list.push_back(*col_item))) { LOG_WARN("fail to push column expr in array", K(ret)); diff --git a/src/sql/rewrite/ob_transform_utils.h b/src/sql/rewrite/ob_transform_utils.h index ab1dcdb4d2..e7ab603b42 100644 --- a/src/sql/rewrite/ob_transform_utils.h +++ b/src/sql/rewrite/ob_transform_utils.h @@ -916,7 +916,8 @@ public: ObSEArray& column_list, bool all_tab, bool &tab_has_alias, - TableItem *&tab_item); + TableItem *&tab_item, + bool &is_empty_table); static int add_column_expr_for_json_object_node(ObTransformerCtx *ctx, ObDMLStmt *stmt, ColumnItem& col_item, @@ -925,6 +926,8 @@ public: ObDMLStmt *stmt, ObRawExpr *param_expr, ObSEArray& param_array); + static int add_dummy_expr_for_json_object_node(ObTransformerCtx *ctx, + ObSEArray& param_array); // end json object with star static int add_cast_for_replace(ObRawExprFactory &expr_factory, const ObRawExpr *from_expr,