diff --git a/src/pl/sys_package/ob_dbms_stats.cpp b/src/pl/sys_package/ob_dbms_stats.cpp index 537c6393a6..8159ad4fb3 100644 --- a/src/pl/sys_package/ob_dbms_stats.cpp +++ b/src/pl/sys_package/ob_dbms_stats.cpp @@ -2811,6 +2811,7 @@ int ObDbmsStats::set_table_prefs(sql::ObExecContext &ctx, param.allocator_ = &ctx.get_allocator(); ObSEArray table_ids; ObStatPrefs *stat_pref = NULL; + bool use_size_auto = false; if (OB_FAIL(check_statistic_table_writeable(ctx))) { LOG_WARN("failed to check tenant is restore", K(ret)); } else if (OB_FAIL(parse_table_part_info(ctx, params.at(0), params.at(1), dummy_param, param))) { @@ -2841,7 +2842,7 @@ int ObDbmsStats::set_table_prefs(sql::ObExecContext &ctx, } else if (OB_FAIL(stat_pref->dump_pref_name_and_value(opt_name, opt_value))) { LOG_WARN("failed to dump pref name and value"); } else if (0 == opt_name.case_compare("METHOD_OPT") && - OB_FAIL(parse_method_opt(ctx, param.allocator_, param.column_params_, opt_value))) { + OB_FAIL(parse_method_opt(ctx, param.allocator_, param.column_params_, opt_value, use_size_auto))) { LOG_WARN("failed to parse method opt", K(ret)); } else if (OB_FAIL(ObDbmsStatsPreferences::set_prefs(ctx, table_ids, opt_name, opt_value))) { LOG_WARN("failed to set prefs", K(ret)); @@ -3995,14 +3996,12 @@ int ObDbmsStats::parse_granularity_and_method_opt(ObExecContext &ctx, int ret = OB_SUCCESS; //virtual table(not include real agent table) doesn't gather histogram. bool is_vt = is_virtual_table(param.table_id_); - ObGranularityType granu_type = ObGranularityType::GRANULARITY_INVALID; - if (OB_FAIL(ObDbmsStatsUtils::parse_granularity(param.granularity_, granu_type))) { - LOG_WARN("failed to parse granularity"); - } else if (OB_FAIL(resovle_granularity(granu_type, param))) { - LOG_WARN("failed to resovle granularity", K(granu_type)); - } else if (0 == param.method_opt_.case_compare("Z") && !is_vt) { + bool use_size_auto = false; + if (0 == param.method_opt_.case_compare("Z") && !is_vt) { if (OB_FAIL(set_default_column_params(param.column_params_))) { LOG_WARN("failed to set default column params", K(ret)); + } else { + use_size_auto = true; } } else { // method_opt => null, do not gather histogram, gather basic column stat @@ -4011,12 +4010,19 @@ int ObDbmsStats::parse_granularity_and_method_opt(ObExecContext &ctx, param.method_opt_.assign_ptr(method_opt_str, strlen(method_opt_str)); } if (OB_FAIL(ObDbmsStats::parse_method_opt(ctx, param.allocator_, - param.column_params_, param.method_opt_))) { + param.column_params_, + param.method_opt_, + use_size_auto))) { LOG_WARN("failed to parse method opt", K(ret)); } } if (OB_SUCC(ret)) { - if (OB_FAIL(process_not_size_manual_column(ctx, param))) { + ObGranularityType granu_type = ObGranularityType::GRANULARITY_INVALID; + if (OB_FAIL(ObDbmsStatsUtils::parse_granularity(param.granularity_, granu_type))) { + LOG_WARN("failed to parse granularity"); + } else if (OB_FAIL(resovle_granularity(granu_type, use_size_auto, param))) { + LOG_WARN("failed to resovle granularity", K(granu_type)); + } else if (OB_FAIL(process_not_size_manual_column(ctx, param))) { LOG_WARN("failed to process not size manual column", K(ret)); } } @@ -4168,9 +4174,11 @@ int ObDbmsStats::parse_set_column_stats_options(ObExecContext &ctx, int ObDbmsStats::parse_method_opt(sql::ObExecContext &ctx, ObIAllocator *allocator, ObIArray &column_params, - const ObString &method_opt) + const ObString &method_opt, + bool &use_size_auto) { int ret = OB_SUCCESS; + use_size_auto = false; if (OB_ISNULL(allocator) || OB_ISNULL(ctx.get_my_session())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected error", K(ret), K(allocator), K(ctx.get_my_session())); @@ -4200,7 +4208,7 @@ int ObDbmsStats::parse_method_opt(sql::ObExecContext &ctx, ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(child_node)); } else if (T_FOR_ALL == child_node->type_) { - if (OB_FAIL(parser_for_all_clause(child_node, column_params))) { + if (OB_FAIL(parser_for_all_clause(child_node, column_params, use_size_auto))) { LOG_WARN("failed to parser for all clause", K(ret)); } else {/*do nothing*/} } else if (T_FOR_COLUMNS == child_node->type_) { @@ -4217,9 +4225,11 @@ int ObDbmsStats::parse_method_opt(sql::ObExecContext &ctx, } int ObDbmsStats::parser_for_all_clause(const ParseNode *for_all_node, - ObIArray &column_params) + ObIArray &column_params, + bool &use_size_auto) { int ret = OB_SUCCESS; + use_size_auto = false; if (OB_ISNULL(for_all_node) || OB_UNLIKELY(for_all_node->type_ != T_FOR_ALL)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("get invalid argument", K(for_all_node), K(ret)); @@ -4243,6 +4253,8 @@ int ObDbmsStats::parser_for_all_clause(const ParseNode *for_all_node, if (OB_SUCC(ret) && NULL != for_all_node->children_[1]) { if (OB_FAIL(parse_size_clause(for_all_node->children_[1], size_conf))) { LOG_WARN("failed to parse size clause", K(ret)); + } else { + use_size_auto = size_conf.is_auto(); } } for (int64_t i = 0; OB_SUCC(ret) && i < column_params.count(); ++i) { @@ -6054,7 +6066,9 @@ bool ObDbmsStats::need_gather_index_stats(const ObTableStatParam ¶m) * * @return */ -int ObDbmsStats::resovle_granularity(ObGranularityType granu_type, ObTableStatParam ¶m) +int ObDbmsStats::resovle_granularity(ObGranularityType granu_type, + const bool use_size_auto, + ObTableStatParam ¶m) { int ret = OB_SUCCESS; if (ObGranularityType::GRANULARITY_AUTO == granu_type) { @@ -6064,7 +6078,7 @@ int ObDbmsStats::resovle_granularity(ObGranularityType granu_type, ObTableStatPa // refine auto granularity based on subpart type if (ObPartitionLevel::PARTITION_LEVEL_TWO == param.part_level_ && !(is_range_part(param.subpart_stat_param_.part_type_) || is_list_part(param.subpart_stat_param_.part_type_))) { - param.subpart_stat_param_.gather_histogram_ = false; + param.subpart_stat_param_.gather_histogram_ = !use_size_auto; } } else if (ObGranularityType::GRANULARITY_ALL == granu_type) { param.global_stat_param_.set_gather_stat(false); diff --git a/src/pl/sys_package/ob_dbms_stats.h b/src/pl/sys_package/ob_dbms_stats.h index 42e4947bb9..3c01620e93 100644 --- a/src/pl/sys_package/ob_dbms_stats.h +++ b/src/pl/sys_package/ob_dbms_stats.h @@ -240,10 +240,12 @@ public: static int parse_method_opt(sql::ObExecContext &ctx, ObIAllocator *allocator, ObIArray &column_params, - const ObString &method_opt); + const ObString &method_opt, + bool &use_size_auto); static int parser_for_all_clause(const ParseNode *for_all_node, - ObIArray &column_params); + ObIArray &column_params, + bool &use_size_auto); static int parser_for_columns_clause(const ParseNode *for_col_node, ObIArray &column_params, @@ -549,9 +551,13 @@ private: static bool is_func_index(const ObTableStatParam &index_param); + static bool need_gather_index_stats(const ObTableStatParam &table_param); - static int resovle_granularity(ObGranularityType granu_type, ObTableStatParam ¶m); + static int resovle_granularity(ObGranularityType granu_type, + const bool use_size_auto, + ObTableStatParam ¶m); + static void decide_modified_part(ObTableStatParam ¶m, const bool cascade_parts); }; diff --git a/src/share/stat/ob_opt_stat_sql_service.cpp b/src/share/stat/ob_opt_stat_sql_service.cpp index 88967d13da..ddbaee91f0 100644 --- a/src/share/stat/ob_opt_stat_sql_service.cpp +++ b/src/share/stat/ob_opt_stat_sql_service.cpp @@ -903,8 +903,12 @@ int ObOptStatSqlService::get_column_stat_sql(const uint64_t tenant_id, char *llc_hex_buf = NULL; int64_t llc_comp_size = 0; int64_t llc_hex_size = 0; - if (OB_FAIL(get_valid_obj_str(stat.get_min_value(), min_meta, allocator, min_str, print_params)) || - OB_FAIL(get_valid_obj_str(stat.get_max_value(), max_meta, allocator, max_str, print_params))) { + if (OB_UNLIKELY(ObHistType::INVALID_TYPE != stat.get_histogram().get_type() && + stat.get_histogram().get_bucket_cnt() == 0)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(stat)); + } else if (OB_FAIL(get_valid_obj_str(stat.get_min_value(), min_meta, allocator, min_str, print_params)) || + OB_FAIL(get_valid_obj_str(stat.get_max_value(), max_meta, allocator, max_str, print_params))) { LOG_WARN("failed to get valid obj str", K(stat.get_min_value()), K(stat.get_max_value())); } else if (OB_FAIL(get_obj_binary_hex_str(stat.get_min_value(), allocator, b_min_str)) || OB_FAIL(get_obj_binary_hex_str(stat.get_max_value(), allocator, b_max_str))) { diff --git a/src/share/stat/ob_topk_hist_estimator.h b/src/share/stat/ob_topk_hist_estimator.h index 6b5a23d2dd..c2e60f7d9d 100644 --- a/src/share/stat/ob_topk_hist_estimator.h +++ b/src/share/stat/ob_topk_hist_estimator.h @@ -14,6 +14,7 @@ #define OB_TOPK_HIST_ESTIMATOR_H #include "share/stat/ob_stat_define.h" +#include "share/rc/ob_tenant_base.h" namespace oceanbase { @@ -53,13 +54,17 @@ class ObTopKFrequencyHistograms used_list_(), free_list_(), topk_map_(), - topk_buf_(), + topk_buf_("OptTopkHist"), use_first_alloc_(true), - obj_buf1_(), - obj_buf2_(), + obj_buf1_("OptTopkHist"), + obj_buf2_("OptTopkHist"), copied_count_(), need_deep_copy_(false) - {} + { + topk_buf_.set_tenant_id(MTL_ID()); + obj_buf1_.set_tenant_id(MTL_ID()); + obj_buf2_.set_tenant_id(MTL_ID()); + } int read_result(const ObObj &result_obj); diff --git a/src/sql/parser/parse_node.h b/src/sql/parser/parse_node.h index c5fe335557..b25120ea19 100644 --- a/src/sql/parser/parse_node.h +++ b/src/sql/parser/parse_node.h @@ -144,6 +144,7 @@ typedef struct _ParseNode 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_forbid_parameter_ : 1; //1 indicate forbid parameter uint32_t reserved_; }; }; diff --git a/src/sql/parser/sql_parser_base.h b/src/sql/parser/sql_parser_base.h index 9a9330fd63..a0c4abd600 100644 --- a/src/sql/parser/sql_parser_base.h +++ b/src/sql/parser/sql_parser_base.h @@ -1011,7 +1011,7 @@ do {\ #define CHECK_MYSQL_COMMENT(p, node)\ do {\ if (p->mysql_compatible_comment_) {\ - node->is_hidden_const_ = 1;\ + node->is_forbid_parameter_ = 1;\ }\ } while(0);\ diff --git a/src/sql/plan_cache/ob_sql_parameterization.cpp b/src/sql/plan_cache/ob_sql_parameterization.cpp index bf350fdcc3..c7a9711dfc 100644 --- a/src/sql/plan_cache/ob_sql_parameterization.cpp +++ b/src/sql/plan_cache/ob_sql_parameterization.cpp @@ -260,7 +260,8 @@ int ObSqlParameterization::is_fast_parse_const(TransformTreeCtx &ctx) || (T_IEEE754_INFINITE == ctx.tree_->type_ && true == ctx.tree_->is_hidden_const_) || (T_IEEE754_NAN == ctx.tree_->type_ && true == ctx.tree_->is_hidden_const_) || (T_SFU_INT == ctx.tree_->type_ && true == ctx.tree_->is_hidden_const_) - || (T_FLOAT == ctx.tree_->type_ && true == ctx.tree_->is_hidden_const_)) { + || (T_FLOAT == ctx.tree_->type_ && true == ctx.tree_->is_hidden_const_) + || true == ctx.tree_->is_forbid_parameter_) { ctx.is_fast_parse_const_ = false; } else { ctx.is_fast_parse_const_ = (IS_DATATYPE_OP(ctx.tree_->type_) diff --git a/src/sql/resolver/ddl/ob_analyze_stmt.cpp b/src/sql/resolver/ddl/ob_analyze_stmt.cpp index 5f728737ca..ecdca33c4a 100644 --- a/src/sql/resolver/ddl/ob_analyze_stmt.cpp +++ b/src/sql/resolver/ddl/ob_analyze_stmt.cpp @@ -38,7 +38,8 @@ ObAnalyzeStmt::ObAnalyzeStmt() is_drop_(false), part_ids_(), subpart_ids_(), - ref_table_type_(share::schema::ObTableType::MAX_TABLE_TYPE) + ref_table_type_(share::schema::ObTableType::MAX_TABLE_TYPE), + gather_subpart_hist_(false) { } @@ -98,6 +99,7 @@ int ObAnalyzeStmt::fill_table_stat_param(ObExecContext &ctx, common::ObTableStat param.global_stat_param_.need_modify_ = partition_name_.empty(); param.part_stat_param_.need_modify_ = !partition_infos_.empty(); param.subpart_stat_param_.need_modify_ = !subpartition_infos_.empty(); + param.subpart_stat_param_.gather_histogram_ = gather_subpart_hist_; } LOG_TRACE("link bug", K(param)); diff --git a/src/sql/resolver/ddl/ob_analyze_stmt.h b/src/sql/resolver/ddl/ob_analyze_stmt.h index adaeeeb457..dd8baa577a 100644 --- a/src/sql/resolver/ddl/ob_analyze_stmt.h +++ b/src/sql/resolver/ddl/ob_analyze_stmt.h @@ -102,6 +102,8 @@ public: int set_part_ids(ObIArray &part_ids); int set_subpart_ids(ObIArray &subpart_ids); + void set_gather_subpart_hist(bool gather_subpart_hist) { gather_subpart_hist_ = gather_subpart_hist; } + TO_STRING_KV(K_(tenant_id), K_(table_id), @@ -112,7 +114,9 @@ public: K_(subpartition_infos), K_(part_ids), K_(subpart_ids), - K_(ref_table_type)); + K_(ref_table_type), + K_(gather_subpart_hist)); + private: uint64_t tenant_id_; ObString database_name_; @@ -141,6 +145,7 @@ private: common::ObSEArray all_partition_infos_; common::ObSEArray all_subpartition_infos_; share::schema::ObTableType ref_table_type_; + bool gather_subpart_hist_; DISALLOW_COPY_AND_ASSIGN(ObAnalyzeStmt); }; diff --git a/src/sql/resolver/ddl/ob_analyze_stmt_resolver.cpp b/src/sql/resolver/ddl/ob_analyze_stmt_resolver.cpp index 4e941a800b..53d1a49390 100644 --- a/src/sql/resolver/ddl/ob_analyze_stmt_resolver.cpp +++ b/src/sql/resolver/ddl/ob_analyze_stmt_resolver.cpp @@ -91,14 +91,15 @@ int ObAnalyzeStmtResolver::resolve_oracle_analyze(const ParseNode &parse_node, ParseNode *table_node = parse_node.children_[0]; ParseNode *part_node = parse_node.children_[1]; ParseNode *statistic_node = parse_node.children_[2]; + bool is_hist_subpart = false; if (OB_ISNULL(table_node) || OB_ISNULL(statistic_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null parse node", K(table_node), K(statistic_node), K(ret)); } else if (OB_FAIL(resolve_table_info(table_node, analyze_stmt))) { LOG_WARN("failed to resolve table info", K(ret)); - } else if (OB_FAIL(resolve_partition_info(part_node, analyze_stmt))) { + } else if (OB_FAIL(resolve_partition_info(part_node, analyze_stmt, is_hist_subpart))) { LOG_WARN("failed to resolve partition info", K(ret)); - } else if (OB_FAIL(resolve_statistic_info(statistic_node, analyze_stmt))) { + } else if (OB_FAIL(resolve_statistic_info(statistic_node, is_hist_subpart, analyze_stmt))) { LOG_WARN("failed to resolve statistic info", K(ret)); } else { /*do nothing*/ } } @@ -116,12 +117,13 @@ int ObAnalyzeStmtResolver::resolve_mysql_update_histogram(const ParseNode &parse ParseNode *table_node = parse_node.children_[0]; ParseNode *column_node = parse_node.children_[1]; ParseNode *bucket_node = parse_node.children_[2]; + bool dumy_bool = false; if (OB_ISNULL(table_node) || OB_ISNULL(column_node) || OB_ISNULL(bucket_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null parse node", K(table_node), K(column_node), K(bucket_node), K(ret)); } else if (OB_FAIL(resolve_table_info(table_node, analyze_stmt))) { LOG_WARN("failed to resolve table info", K(ret)); - } else if (OB_FAIL(resolve_partition_info(NULL, analyze_stmt))) { + } else if (OB_FAIL(resolve_partition_info(NULL, analyze_stmt, dumy_bool))) { LOG_WARN("failed to resolve partition info", K(ret)); } else if (OB_FAIL(resolve_mysql_column_bucket_info(column_node, bucket_node->value_, @@ -148,12 +150,13 @@ int ObAnalyzeStmtResolver::resolve_mysql_delete_histogram(const ParseNode &parse } else { ParseNode *table_node = parse_node.children_[0]; ParseNode *column_node = parse_node.children_[1]; + bool dumy_bool = false; if (OB_ISNULL(table_node) || OB_ISNULL(column_node)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null parse node", K(ret)); } else if (OB_FAIL(resolve_table_info(table_node, analyze_stmt))) { LOG_WARN("failed to resolve table info", K(ret)); - } else if (OB_FAIL(resolve_partition_info(NULL, analyze_stmt))) { + } else if (OB_FAIL(resolve_partition_info(NULL, analyze_stmt, dumy_bool))) { LOG_WARN("failed to resolve partition info", K(ret)); } else if (OB_FAIL(resolve_mysql_column_bucket_info(column_node, 0, analyze_stmt))) { @@ -238,7 +241,8 @@ int ObAnalyzeStmtResolver::resolve_table_info(const ParseNode *table_node, } int ObAnalyzeStmtResolver::resolve_partition_info(const ParseNode *part_node, - ObAnalyzeStmt &analyze_stmt) + ObAnalyzeStmt &analyze_stmt, + bool &is_hist_subpart) { int ret = OB_SUCCESS; const ObTableSchema *table_schema = NULL; @@ -248,6 +252,7 @@ int ObAnalyzeStmtResolver::resolve_partition_info(const ParseNode *part_node, ObSEArray part_ids; ObSEArray subpart_ids; bool is_subpart_name = false; + is_hist_subpart = false; ObString &partition_name = analyze_stmt.get_partition_name(); if (OB_ISNULL(schema_checker_)) { @@ -310,10 +315,15 @@ int ObAnalyzeStmtResolver::resolve_partition_info(const ParseNode *part_node, } } } + if (OB_SUCC(ret) && share::schema::ObPartitionLevel::PARTITION_LEVEL_TWO == table_schema->get_part_level()) { + is_hist_subpart = (is_range_part(table_schema->get_sub_part_option().get_part_func_type()) || + is_list_part(table_schema->get_sub_part_option().get_part_func_type())); + } return ret; } int ObAnalyzeStmtResolver::resolve_statistic_info(const ParseNode *statistic_node, + const bool is_hist_subpart, ObAnalyzeStmt &analyze_stmt) { int ret = OB_SUCCESS; @@ -328,7 +338,7 @@ int ObAnalyzeStmtResolver::resolve_statistic_info(const ParseNode *statistic_nod } else { const ParseNode *for_clause_node = statistic_node->children_[0]; const ParseNode *sample_clause_node = statistic_node->children_[1]; - if (OB_FAIL(resolve_for_clause_info(for_clause_node, analyze_stmt))) { + if (OB_FAIL(resolve_for_clause_info(for_clause_node, is_hist_subpart, analyze_stmt))) { LOG_WARN("failed to resolve for clause info", K(ret)); } else if (OB_FAIL(resolve_sample_clause_info(sample_clause_node, analyze_stmt))) { LOG_WARN("failed to resolve sample clause info", K(ret)); @@ -338,6 +348,7 @@ int ObAnalyzeStmtResolver::resolve_statistic_info(const ParseNode *statistic_nod } int ObAnalyzeStmtResolver::resolve_for_clause_info(const ParseNode *for_clause_node, + const bool is_hist_subpart, ObAnalyzeStmt &analyze_stmt) { int ret = OB_SUCCESS; @@ -353,10 +364,13 @@ int ObAnalyzeStmtResolver::resolve_for_clause_info(const ParseNode *for_clause_n } else if (NULL == for_clause_node) { if (OB_FAIL(pl::ObDbmsStats::set_default_column_params(analyze_stmt.get_column_params()))) { LOG_WARN("failed to set default column params", K(ret)); + } else { + analyze_stmt.set_gather_subpart_hist(is_hist_subpart); } } else { for (int64_t i = 0; OB_SUCC(ret) && i < for_clause_node->num_child_; i++) { if (OB_FAIL(resolve_for_clause_element(for_clause_node->children_[i], + is_hist_subpart, analyze_stmt))) { LOG_WARN("failed to resolve for clause element", K(ret)); } else { /*do nothing*/ } @@ -366,6 +380,7 @@ int ObAnalyzeStmtResolver::resolve_for_clause_info(const ParseNode *for_clause_n } int ObAnalyzeStmtResolver::resolve_for_clause_element(const ParseNode *for_clause_node, + const bool is_hist_subpart, ObAnalyzeStmt &analyze_stmt) { int ret = OB_SUCCESS; @@ -379,15 +394,21 @@ int ObAnalyzeStmtResolver::resolve_for_clause_element(const ParseNode *for_claus LOG_WARN("analyze table not supported yet", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "analyze table"); } else if (T_FOR_ALL == for_clause_node->type_) { + bool use_size_auto = false; if (OB_FAIL(pl::ObDbmsStats::parser_for_all_clause(for_clause_node, - analyze_stmt.get_column_params()))) { + analyze_stmt.get_column_params(), + use_size_auto))) { LOG_WARN("failed to resolve for all clause", K(ret)); + } else { + analyze_stmt.set_gather_subpart_hist(!use_size_auto || (use_size_auto && is_hist_subpart)); } } else if (T_FOR_COLUMNS == for_clause_node->type_) { if (OB_FAIL(pl::ObDbmsStats::parser_for_columns_clause(for_clause_node, analyze_stmt.get_column_params(), all_for_col))) { LOG_WARN("failed to parser for columns clause", K(ret)); + } else { + analyze_stmt.set_gather_subpart_hist(true); } } else { ret = OB_ERR_UNEXPECTED; diff --git a/src/sql/resolver/ddl/ob_analyze_stmt_resolver.h b/src/sql/resolver/ddl/ob_analyze_stmt_resolver.h index 1ef273018e..61a6b4b77c 100644 --- a/src/sql/resolver/ddl/ob_analyze_stmt_resolver.h +++ b/src/sql/resolver/ddl/ob_analyze_stmt_resolver.h @@ -41,12 +41,16 @@ private: int resolve_table_info(const ParseNode *table_node, ObAnalyzeStmt &analyze_stmt); int resolve_partition_info(const ParseNode *part_node, - ObAnalyzeStmt &analyze_stmt); + ObAnalyzeStmt &analyze_stmt, + bool &is_hist_subpart); int resolve_statistic_info(const ParseNode *statistic_node, + const bool is_hist_subpart, ObAnalyzeStmt &analyze_stmt); int resolve_for_clause_info(const ParseNode *for_clause_node, + const bool is_hist_subpart, ObAnalyzeStmt &analyze_stmt); int resolve_for_clause_element(const ParseNode *for_clause_node, + const bool is_hist_subpart, ObAnalyzeStmt &analyze_stmt); int resolve_sample_clause_info(const ParseNode *sample_clause_node, ObAnalyzeStmt &analyze_stmt);