/** * Copyright (c) 2021 OceanBase * OceanBase CE is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. */ #ifndef OCEANBASE_SQL_PLAN_CACHE_OB_SQL_PARAMETERIZATION_ #define OCEANBASE_SQL_PLAN_CACHE_OB_SQL_PARAMETERIZATION_ #include "lib/hash/ob_link_hashmap.h" #include "lib/string/ob_string.h" #include "lib/container/ob_bit_set.h" #include "lib/container/ob_vector.h" #include "lib/container/ob_se_array.h" #include "lib/utility/ob_print_utils.h" #include "common/object/ob_object.h" #include "sql/parser/ob_parser.h" #include "sql/parser/ob_fast_parser.h" #include "sql/session/ob_sql_session_info.h" #include "sql/plan_cache/ob_id_manager_allocator.h" #include "sql/plan_cache/ob_plan_cache_util.h" namespace oceanbase { namespace common { class ObIAllocator; } namespace sql { typedef common::LinkHashValue ParameterizationHashValue; struct SqlInfo: public ParameterizationHashValue { SqlInfo &operator=(const SqlInfo &that) { total_ = that.total_; not_param_index_ = that.not_param_index_; neg_param_index_ = that.neg_param_index_; fixed_param_index_ = that.fixed_param_index_; param_charset_type_ = that.param_charset_type_; sql_traits_ = that.sql_traits_; last_active_time_ = that.last_active_time_; hit_count_ = that.hit_count_; trans_from_minus_index_ = that.trans_from_minus_index_; must_be_positive_index_ = that.must_be_positive_index_; ps_not_param_offsets_ = that.ps_not_param_offsets_; fixed_param_idx_ = that.fixed_param_idx_; no_check_type_offsets_ = that.no_check_type_offsets_; need_check_type_param_offsets_ = that.need_check_type_param_offsets_; ps_need_parameterized_ = that.ps_need_parameterized_; parse_infos_ = that.parse_infos_; need_check_fp_ = that.need_check_fp_; return *this; } void destroy() {} int64_t total_; common::ObBitSet<> not_param_index_; common::ObBitSet<> neg_param_index_; common::ObBitSet<> fixed_param_index_;//记录限流语句中可参数化的位置不为?的位置 common::ObBitSet<> trans_from_minus_index_; common::ObBitSet<> must_be_positive_index_; // 记录那些常量必须是正数 common::ObSEArray param_charset_type_; ObSqlTraits sql_traits_; int64_t last_active_time_; uint64_t hit_count_; common::ObSEArray ps_not_param_offsets_; //used for ps mode not param common::ObSEArray fixed_param_idx_; common::ObSEArray no_check_type_offsets_; common::ObBitSet<> need_check_type_param_offsets_; // Check whether the ps parameter can be a parameterized template. // this is the optimization of the following statement hitting the same plan_cache: // prepare stmt from 'select * from t1 where c1 = 1 and c2 = 1'; // prepare stmt from 'select * from t1 where c1 = 1 and c2 = ?'; // prepare stmt from 'select * from t1 where c1 = ? and c2 = ?'; // but if the SQL statement contains "is null" or "is not null" or "no wait 1", etc. // this optimization is not done // because this will cause the parameterized SQL to report a syntax error in the parser. // such as prepare stmt from 'select * from t1 where c1 = ? and c2 is null'; bool ps_need_parameterized_; common::ObSEArray parse_infos_; bool need_check_fp_; SqlInfo(); }; struct TransformTreeCtx; struct SelectItemTraverseCtx; enum SQL_EXECUTION_MODE { INVALID_MODE = -1, TEXT_MODE, PS_PREPARE_MODE, PS_EXECUTE_MODE, PL_PREPARE_MODE, PL_EXECUTE_MODE, MAX_EXECUTION_MODE }; class ObSqlParameterization { public: static const int64_t SQL_PARAMETERIZATION_BUCKET_NUM = 1L << 20; static const int64_t NO_VALUES = -1; //表示没有values() static const int64_t VALUE_LIST_LEVEL = 0; //表示在parse的T_VALUE_LIST层 static const int64_t VALUE_VECTOR_LEVEL = 1;//表示在parse的T_VALUE_VECTOR层 static const int64_t ASSIGN_LIST_LEVEL = 0; static const int64_t ASSIGN_ITEM_LEVEL = 1; ObSqlParameterization() {} virtual ~ObSqlParameterization() {} static int fast_parser(common::ObIAllocator &allocator, const FPContext &fp_ctx, const common::ObString &sql, ObFastParserResult &fp_result); static int transform_syntax_tree(common::ObIAllocator &allocator, const ObSQLSessionInfo &session, const ObIArray *raw_params, ParseNode *tree, SqlInfo &sql_info, ParamStore ¶ms, SelectItemParamInfoArray *select_item_param_infos, share::schema::ObMaxConcurrentParam::FixParamStore &fixed_param_store, bool is_transform_outline, SQL_EXECUTION_MODE execution_mode = INVALID_MODE, const ObIArray *udr_fixed_params = NULL, bool is_from_pl = false); static int raw_fast_parameterize_sql(common::ObIAllocator &allocator, const ObSQLSessionInfo &session, const common::ObString &sql, common::ObString &no_param_sql, common::ObIArray &raw_params, ParseMode parse_mode = FP_MODE); static int check_and_generate_param_info(const common::ObIArray &raw_params, const SqlInfo ¬_param_info, common::ObIArray &special_param_info); static int transform_neg_param(ObIArray &pc_params); static int construct_not_param(const ObString &no_param_sql, ObPCParam *pc_param, char *buf, int32_t buf_len, int32_t &pos, int32_t &idx); static int construct_neg_param(const ObString &no_param_sql, ObPCParam *pc_param, char *buf, int32_t buf_len, int32_t &pos, int32_t &idx); static int construct_trans_neg_param(const ObString &no_param_sql, ObPCParam *pc_param, char *buf, int32_t buf_len, int32_t &pos, int32_t &idx); static int construct_sql(const common::ObString &no_param_sql, common::ObIArray ¬_params, char *buf, int32_t buf_len, int32_t &pos); static int construct_sql_for_pl(const common::ObString &no_param_sql, common::ObIArray ¬_params, char *buf, int32_t buf_len, int32_t &pos); static int parameterize_syntax_tree(common::ObIAllocator &allocator, bool is_transform_outline, ObPlanCacheCtx &pc_ctx, ParseNode *tree, ParamStore ¶ms, ObCollationType cs_type); static int gen_special_param_info(SqlInfo &sql_info, ObPlanCacheCtx &pc_ctx); static int gen_ps_not_param_var(const ObIArray &offsets, ParamStore ¶ms, ObPlanCacheCtx &pc_ctx); static int construct_no_check_type_params(const ObIArray &no_check_type_offsets, const ObBitSet<> &need_check_type_offsets, ParamStore ¶ms); static int insert_neg_sign(common::ObIAllocator &alloc_buf, ParseNode *node); static bool is_tree_not_param(const ParseNode *tree); static SQL_EXECUTION_MODE get_sql_execution_mode(ObPlanCacheCtx &pc_ctx); static bool is_prepare_mode(SQL_EXECUTION_MODE mode); static bool is_execute_mode(SQL_EXECUTION_MODE mode); static bool is_ignore_scale_check(TransformTreeCtx &ctx, const ParseNode *parent); private: DISALLOW_COPY_AND_ASSIGN(ObSqlParameterization); static int is_fast_parse_const(TransformTreeCtx &ctx); static bool is_node_not_param(TransformTreeCtx &ctx); static bool is_udr_not_param(TransformTreeCtx &ctx); static int transform_tree(TransformTreeCtx &ctx, const ObSQLSessionInfo &session_info); static int add_param_flag(const ParseNode *node, SqlInfo &sql_info); static int add_not_param_flag(const ParseNode *node, SqlInfo &sql_info); static int add_varchar_charset(const ParseNode *node, SqlInfo &sql_info); static int mark_args(ParseNode *arg_tree, const bool *mark_arr, int64_t arg_num, SqlInfo &sql_info); static int mark_tree(ParseNode *tree, SqlInfo &sql_info); static int get_related_user_vars(const ParseNode *tree, common::ObIArray &user_vars); static int get_select_item_param_info(const common::ObIArray &raw_params, ParseNode *tree, SelectItemParamInfoArray *select_item_param_infos); static int parameterize_fields(SelectItemTraverseCtx &ctx); static int resolve_paramed_const(SelectItemTraverseCtx &ctx); static int transform_minus_op(ObIAllocator &, ParseNode *, bool is_from_pl=false); static int find_leftest_const_node(ParseNode &cur_node, ParseNode *&const_node); static bool need_fast_parser(const ObString &sql); }; } } #endif /* _OB_SQL_PARAMETERIZATION_H */