[FEAT MERGE]implement user-defined rewrite rules

This commit is contained in:
obdev
2022-12-30 08:10:42 +00:00
committed by ob-robot
parent 21c0bac716
commit 9dcc0a529e
100 changed files with 5540 additions and 315 deletions

View File

@ -32,6 +32,7 @@
#include "sql/engine/ob_physical_plan.h"
#include "sql/plan_cache/ob_plan_cache_callback.h"
#include "sql/plan_cache/ob_cache_object_factory.h"
#include "sql/udr/ob_udr_mgr.h"
#include "pl/ob_pl.h"
#include "pl/ob_pl_package.h"
#include "observer/ob_req_time_service.h"
@ -389,13 +390,16 @@ int ObPlanCache::check_after_get_plan(int tmp_ret,
ObPhysicalPlan *plan = NULL;
bool need_late_compilation = false;
ObJITEnableMode jit_mode = OFF;
omt::ObTenantConfigGuard tenant_config(TENANT_CONF(MTL_ID()));
ObPlanCacheCtx &pc_ctx = static_cast<ObPlanCacheCtx&>(ctx);
if (cache_obj != NULL && ObLibCacheNameSpace::NS_CRSR == cache_obj->get_ns()) {
plan = static_cast<ObPhysicalPlan *>(cache_obj);
}
if (OB_SUCC(ret)) {
if (OB_ISNULL(pc_ctx.sql_ctx_.session_info_)) {
if (!tenant_config.is_valid()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("tenant config is invalid", K(ret));
} else if (OB_ISNULL(pc_ctx.sql_ctx_.session_info_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected null session info", K(ret));
} else if (OB_FAIL(pc_ctx.sql_ctx_.session_info_->get_jit_enabled_mode(jit_mode))) {
@ -404,17 +408,39 @@ int ObPlanCache::check_after_get_plan(int tmp_ret,
// do nothing
}
}
if (OB_SUCC(ret) &&
plan != NULL &&
AUTO == jit_mode && // only use late compilation when jit_mode is auto
OB_FAIL(need_late_compile(plan, need_late_compilation))) {
LOG_WARN("failed to check for late compilation", K(ret));
} else {
// set context's need_late_compile_ for upper layer to proceed
pc_ctx.sql_ctx_.need_late_compile_ = need_late_compilation;
if (OB_SUCC(ret) && plan != NULL) {
bool is_exists = false;
sql::ObUDRMgr *rule_mgr = MTL(sql::ObUDRMgr*);
// when the global rule version changes or enable_user_defined_rewrite_rules changes
// it is necessary to check whether the physical plan are expired
if ((plan->get_rule_version() != rule_mgr->get_rule_version()
|| plan->is_enable_udr() != tenant_config->enable_user_defined_rewrite_rules)) {
if (OB_FAIL(rule_mgr->fuzzy_check_by_pattern_digest(pc_ctx.get_normalized_pattern_digest(), is_exists))) {
LOG_WARN("failed to fuzzy check by pattern digest", K(ret));
} else if (is_exists || plan->is_rewrite_sql()) {
ret = OB_OLD_SCHEMA_VERSION;
LOG_TRACE("Obsolete user-defined rewrite rules require eviction plan", K(ret),
K(is_exists), K(pc_ctx.raw_sql_), K(plan->is_enable_udr()), K(tenant_config->enable_user_defined_rewrite_rules),
K(plan->is_rewrite_sql()), K(plan->get_rule_version()), K(rule_mgr->get_rule_version()));
} else {
plan->set_rule_version(rule_mgr->get_rule_version());
plan->set_is_enable_udr(tenant_config->enable_user_defined_rewrite_rules);
}
}
if (OB_SUCC(ret)) {
if (AUTO == jit_mode && // only use late compilation when jit_mode is auto
OB_FAIL(need_late_compile(plan, need_late_compilation))) {
LOG_WARN("failed to check for late compilation", K(ret));
} else {
// set context's need_late_compile_ for upper layer to proceed
pc_ctx.sql_ctx_.need_late_compile_ = need_late_compilation;
}
}
}
// if schema expired, update pcv set;
if (OB_OLD_SCHEMA_VERSION == ret || (plan != NULL && plan->is_expired()) || need_late_compilation) {
if (OB_OLD_SCHEMA_VERSION == ret
|| (plan != NULL && plan->is_expired())
|| need_late_compilation) {
if (plan != NULL && plan->is_expired()) {
LOG_INFO("the statistics of table is stale and evict plan.", K(plan->stat_));
}
@ -583,14 +609,17 @@ int ObPlanCache::construct_fast_parser_result(common::ObIAllocator &allocator,
LOG_WARN("failed to construct plan cache key", K(ret));
} else if (enable_exact_mode) {
(void)fp_result.pc_key_.name_.assign_ptr(raw_sql.ptr(), raw_sql.length());
} else if (OB_FAIL(ObSqlParameterization::fast_parser(allocator,
sql_mode,
conn_coll,
raw_sql,
pc_ctx.sql_ctx_.handle_batched_multi_stmt(),
fp_result))) {
LOG_WARN("failed to fast parser", K(ret), K(sql_mode), K(pc_ctx.raw_sql_));
} else { /*do nothing*/ }
} else {
FPContext fp_ctx(conn_coll);
fp_ctx.enable_batched_multi_stmt_ = pc_ctx.sql_ctx_.handle_batched_multi_stmt();
fp_ctx.sql_mode_ = sql_mode;
if (OB_FAIL(ObSqlParameterization::fast_parser(allocator,
fp_ctx,
raw_sql,
fp_result))) {
LOG_WARN("failed to fast parser", K(ret), K(sql_mode), K(pc_ctx.raw_sql_));
} else { /*do nothing*/ }
}
}
return ret;
}
@ -1579,6 +1608,7 @@ int ObPlanCache::add_ps_plan(T *plan, ObPlanCacheCtx &pc_ctx)
ret = OB_ERR_UNEXPECTED;
SQL_PC_LOG(WARN, "pc_ctx.raw_sql_.ptr() is NULL, cannot add plan to plan cache by sql", K(ret));
} else {
pc_ctx.fp_result_.pc_key_.is_ps_mode_ = true;
pc_ctx.fp_result_.pc_key_.name_ = pc_ctx.raw_sql_;
uint64_t old_stmt_id = pc_ctx.fp_result_.pc_key_.key_id_;
// the remote plan uses key_id is 0 to distinguish, so if key_id is 0, it cannot be set to OB_INVALID_ID

View File

@ -26,6 +26,7 @@
#include "sql/plan_cache/ob_i_lib_cache_context.h"
#include "sql/ob_sql_utils.h"
#include "sql/plan_cache/ob_plan_cache_util.h"
#include "sql/udr/ob_udr_struct.h"
namespace oceanbase
{
@ -180,6 +181,11 @@ struct NotParamInfo
TO_STRING_KV(K_(idx), K_(raw_text));
};
typedef common::ObSEArray<NotParamInfo, 4> NotParamInfoList;
// Template SQL Constant Constraints
typedef common::ObSEArray<NotParamInfoList, 4> TplSqlConstCons;
struct PsNotParamInfo
{
int64_t idx_;
@ -198,16 +204,28 @@ public:
raw_params_(&inner_alloc_),
ps_params_(&inner_alloc_),
cache_params_(NULL)
{}
{
reset_question_mark_ctx();
}
ObPlanCacheKey pc_key_; //plan cache key, parameterized by fast parser
common::ObFixedArray<ObPCParam *, common::ObIAllocator> raw_params_;
common::ObFixedArray<const common::ObObjParam *, common::ObIAllocator> ps_params_;
ParamStore *cache_params_;
ObQuestionMarkCtx question_mark_ctx_;
void reset() {
pc_key_.reset();
raw_params_.reuse();
ps_params_.reuse();
cache_params_ = NULL;
}
void reset_question_mark_ctx()
{
question_mark_ctx_.name_ = NULL;
question_mark_ctx_.count_ = 0;
question_mark_ctx_.capacity_ = 0;
question_mark_ctx_.by_ordinal_ = false;
question_mark_ctx_.by_name_ = false;
question_mark_ctx_.by_defined_name_ = false;
}
TO_STRING_KV(K(pc_key_), K(raw_params_), K(ps_params_), K(cache_params_));
};
@ -294,7 +312,13 @@ struct ObPlanCacheCtx : public ObILibCacheCtx
need_add_obj_stat_(true),
is_inner_sql_(false),
is_original_ps_mode_(false),
ab_params_(NULL)
ab_params_(NULL),
is_rewrite_sql_(false),
rule_name_(),
def_name_ctx_(NULL),
fixed_param_info_list_(allocator),
dynamic_param_info_list_(allocator),
tpl_sql_const_cons_(allocator)
{
fp_result_.pc_key_.is_ps_mode_ = is_ps_mode_;
}
@ -329,6 +353,17 @@ struct ObPlanCacheCtx : public ObILibCacheCtx
return ret;
}
uint64_t get_normalized_pattern_digest() const
{
common::ObString normalized_pattern;
if (is_ps_mode_ || fp_result_.pc_key_.name_.empty()) {
normalized_pattern = raw_sql_;
} else {
normalized_pattern = fp_result_.pc_key_.name_;
}
return normalized_pattern.hash();
}
int is_retry(bool &v) const; //是否在重试之中
int is_retry_for_dup_tbl(bool &v) const; //仅复制表原因的重试才会设置为true
void set_begin_commit_stmt() { begin_commit_stmt_ = true; }
@ -337,6 +372,8 @@ struct ObPlanCacheCtx : public ObILibCacheCtx
bool is_ps_execute_stage() { return is_ps_execute_stage_; }
void set_is_inner_sql(bool v) { is_inner_sql_ = v; };
bool is_inner_sql() const { return is_inner_sql_; }
void set_is_rewrite_sql(bool v) { is_rewrite_sql_ = v; }
bool is_rewrite_sql() const { return is_rewrite_sql_; }
TO_STRING_KV(
K(is_ps_mode_),
K(raw_sql_),
@ -353,6 +390,12 @@ struct ObPlanCacheCtx : public ObILibCacheCtx
K(fixed_param_idx_),
K(need_add_obj_stat_),
K(is_inner_sql_),
K(is_rewrite_sql_),
K(rule_name_),
K(def_name_ctx_),
K(fixed_param_info_list_),
K(dynamic_param_info_list_),
K(tpl_sql_const_cons_),
K(is_original_ps_mode_)
);
bool is_ps_mode_; //control use which variables to do match
@ -402,6 +445,15 @@ struct ObPlanCacheCtx : public ObILibCacheCtx
bool is_inner_sql_;
bool is_original_ps_mode_;
ParamStore *ab_params_; // arraybinding batch parameters,
// ********** for rewrite rule **********
bool is_rewrite_sql_;
common::ObString rule_name_;
QuestionMarkDefNameCtx *def_name_ctx_;
common::ObFixedArray<FixedParamValue, common::ObIAllocator> fixed_param_info_list_;
common::ObFixedArray<DynamicParamInfo, common::ObIAllocator> dynamic_param_info_list_;
common::ObFixedArray<NotParamInfoList, common::ObIAllocator> tpl_sql_const_cons_;
// ********** for rewrite end **********
};
struct ObPlanCacheStat

View File

@ -490,6 +490,10 @@ struct ObPlanStat
common::ObString config_str_;
common::ObString raw_sql_; //记录生成plan时的原始sql
common::ObCollationType sql_cs_type_;
common::ObString rule_name_;
bool is_rewrite_sql_;
int64_t rule_version_; // the rule version when query rewrite generates a plan
bool enable_udr_;
//******** for spm ******
//该计划是否正在演进过程中
bool is_evolution_;
@ -589,6 +593,10 @@ struct ObPlanStat
outline_id_(common::OB_INVALID_ID),
is_last_exec_succ_(true),
sql_cs_type_(common::CS_TYPE_INVALID),
rule_name_(),
is_rewrite_sql_(false),
rule_version_(OB_INVALID_VERSION),
enable_udr_(false),
is_evolution_(false),
db_id_(common::OB_INVALID_ID),
constructed_sql_(),
@ -660,6 +668,10 @@ struct ObPlanStat
outline_id_(rhs.outline_id_),
is_last_exec_succ_(rhs.is_last_exec_succ_),
sql_cs_type_(rhs.sql_cs_type_),
rule_name_(),
is_rewrite_sql_(false),
rule_version_(OB_INVALID_VERSION),
enable_udr_(false),
is_evolution_(rhs.is_evolution_),
db_id_(rhs.db_id_),
evolution_stat_(rhs.evolution_stat_),

View File

@ -24,6 +24,8 @@
#include "sql/plan_cache/ob_plan_cache.h"
#include "sql/plan_cache/ob_plan_set.h"
#include "sql/session/ob_sql_session_info.h"
#include "sql/udr/ob_udr_mgr.h"
#include "sql/udr/ob_udr_utils.h"
#include "share/ob_duplicate_scope_define.h"
#include "pl/ob_pl_stmt.h"
using namespace oceanbase::share::schema;
@ -154,6 +156,42 @@ ObPlanCacheValue::ObPlanCacheValue()
MEMSET(sql_id_, 0, sizeof(sql_id_));
}
int ObPlanCacheValue::assign_udr_infos(ObPlanCacheCtx &pc_ctx)
{
int ret = OB_SUCCESS;
if (OB_FAIL(dynamic_param_list_.assign(pc_ctx.dynamic_param_info_list_))) {
LOG_WARN("fail to assign dynamic param info list", K(ret));
} else if (OB_FAIL(tpl_sql_const_cons_.assign(pc_ctx.tpl_sql_const_cons_))) {
LOG_WARN("failed to assign tpl sql const cons", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < tpl_sql_const_cons_.count(); ++i) {
NotParamInfoList &not_param_list = tpl_sql_const_cons_.at(i);
std::sort(not_param_list.begin(), not_param_list.end(),
[](NotParamInfo &l, NotParamInfo &r) { return (l.idx_ < r.idx_); });
for (int64_t j = 0; OB_SUCC(ret) && j < not_param_list.count(); ++j) {
if (OB_FAIL(ob_write_string(*pc_alloc_,
not_param_list.at(j).raw_text_,
not_param_list.at(j).raw_text_))) {
LOG_WARN("deep_copy_obj failed", K(i), K(not_param_list.at(j)));
}
}
}
}
return ret;
}
void ObPlanCacheValue::reset_tpl_sql_const_cons()
{
for (int64_t i = 0; i < tpl_sql_const_cons_.count(); ++i) {
NotParamInfoList &not_param_list = tpl_sql_const_cons_.at(i);
for (int64_t j = 0; j < not_param_list.count(); ++j) {
pc_alloc_->free(not_param_list.at(j).raw_text_.ptr());
not_param_list.at(j).raw_text_.reset();
}
}
tpl_sql_const_cons_.reset();
}
int ObPlanCacheValue::init(ObPCVSet *pcv_set, const ObILibCacheObject *cache_obj, ObPlanCacheCtx &pc_ctx)
{
int ret = OB_SUCCESS;
@ -207,6 +245,8 @@ int ObPlanCacheValue::init(ObPCVSet *pcv_set, const ObILibCacheObject *cache_obj
pc_ctx.sql_ctx_.schema_guard_))) {
LOG_WARN("failed to set stored schema objs",
K(ret), K(plan->get_dependency_table()), K(pc_ctx.sql_ctx_.schema_guard_));
} else if (OB_FAIL(assign_udr_infos(pc_ctx))) {
LOG_WARN("failed to assign user-defined rule infos", K(ret));
} else {
//deep copy special param raw text
if (pc_ctx.is_ps_mode_) {
@ -230,6 +270,10 @@ int ObPlanCacheValue::init(ObPCVSet *pcv_set, const ObILibCacheObject *cache_obj
LOG_WARN("fail to deep copy param raw text", K(ret));
}
} //for end
if (OB_SUCC(ret)) {
std::sort(not_param_info_.begin(), not_param_info_.end(),
[](NotParamInfo &l, NotParamInfo &r) { return (l.idx_ < r.idx_); });
}
}
//deep copy constructed sql
if (OB_SUCC(ret)) {
@ -430,6 +474,13 @@ int ObPlanCacheValue::choose_plan(ObPlanCacheCtx &pc_ctx,
LOG_WARN("failed to resolver row params", K(ret));
}
}
// cons user-defined rule param store
if (OB_SUCC(ret)) {
ParamStore param_store( (ObWrapperAllocator(pc_ctx.allocator_)) );
if (OB_FAIL(ObUDRUtils::cons_udr_param_store(dynamic_param_list_, pc_ctx, param_store))) {
LOG_WARN("failed to construct user-defined rule param store", K(ret));
}
}
if (OB_SUCC(ret)) {
ObPhysicalPlanCtx *phy_ctx = pc_ctx.exec_ctx_.get_physical_plan_ctx();
if (NULL != phy_ctx) {
@ -792,6 +843,54 @@ int ObPlanCacheValue::check_not_param_value(const ObFastParserResult &fp_result
return ret;
}
int ObPlanCacheValue::cmp_not_param_info(const NotParamInfoList &l_param_info_list,
const NotParamInfoList &r_param_info_list,
bool &is_equal)
{
int ret = OB_SUCCESS;
is_equal = true;
if (l_param_info_list.count() != r_param_info_list.count()) {
is_equal = false;
} else {
for (int64_t i = 0; OB_SUCC(ret) && is_equal && i < l_param_info_list.count(); ++i) {
const NotParamInfo &l_param_info = l_param_info_list.at(i);
const NotParamInfo &r_param_info = r_param_info_list.at(i);
if (l_param_info.idx_ != r_param_info.idx_) {
is_equal = false;
LOG_DEBUG("compare not param info", K(l_param_info), K(r_param_info));
} else if (0 != l_param_info.raw_text_.compare(r_param_info.raw_text_)) {
is_equal = false;
LOG_DEBUG("compare not param info", K(l_param_info), K(r_param_info));
}
}
}
return ret;
}
int ObPlanCacheValue::check_tpl_sql_const_cons(const ObFastParserResult &fp_result,
const TplSqlConstCons &tpl_cst_cons_list,
bool &is_same)
{
int ret = OB_SUCCESS;
is_same = false;
bool is_match_tpl_cst_cons = false;
for (int64_t i = 0; OB_SUCC(ret) && !is_match_tpl_cst_cons && i < tpl_cst_cons_list.count(); ++i) {
const NotParamInfoList &not_param_list = tpl_cst_cons_list.at(i);
if (OB_FAIL(check_not_param_value(fp_result, not_param_list, is_match_tpl_cst_cons))) {
LOG_WARN("failed to check not param value", K(ret));
} else if (is_match_tpl_cst_cons
&& OB_FAIL(cmp_not_param_info(not_param_list, not_param_info_, is_same))) {
LOG_WARN("failed to cmp not param info", K(ret));
}
}
if (OB_SUCC(ret) && !is_match_tpl_cst_cons && !is_same) {
if (OB_FAIL(check_not_param_value(fp_result, not_param_info_, is_same))) {
LOG_WARN("failed to check not param value", K(ret));
}
}
return ret;
}
int ObPlanCacheValue::get_outline_param_index(ObExecContext &exec_ctx, int64_t &param_idx) const
{
int ret = OB_SUCCESS;
@ -1091,6 +1190,7 @@ void ObPlanCacheValue::reset()
neg_param_index_.reset();
param_charset_type_.reset();
sql_traits_.reset();
reset_tpl_sql_const_cons();
if (OB_SUCCESS != outline_params_wrapper_.destroy()) {
LOG_ERROR("fail to destroy ObOutlineParamWrapper");
@ -1338,10 +1438,10 @@ int ObPlanCacheValue::match(ObPlanCacheCtx &pc_ctx,
LOG_DEBUG("match", K(not_param_var_[i].idx_), K(not_param_var_[i].ps_param_), KPC(ps_param));
}
} else {
if (OB_FAIL(check_not_param_value(pc_ctx.fp_result_,
not_param_info_,
is_same))) {
LOG_WARN("failed to check not param value", K(ret));
if (OB_FAIL(check_tpl_sql_const_cons(pc_ctx.fp_result_,
tpl_sql_const_cons_,
is_same))) {
LOG_WARN("failed to check tpl sql const cons", K(ret));
}
}

View File

@ -332,6 +332,15 @@ private:
static int rm_space_for_neg_num(ParseNode *param_node, ObIAllocator &allocator);
int assign_udr_infos(ObPlanCacheCtx &pc_ctx);
void reset_tpl_sql_const_cons();
int check_tpl_sql_const_cons(const ObFastParserResult &fp_result,
const TplSqlConstCons &tpl_cst_cons_list,
bool &is_same);
int cmp_not_param_info(const NotParamInfoList &l_param_info_list,
const NotParamInfoList &r_param_info_list,
bool &is_equal);
friend class ::test::TestPlanSet_basic_Test;
friend class ::test::TestPlanCacheValue_basic_Test;
private:
@ -387,6 +396,35 @@ private:
common::ObFixedArray<PCVSchemaObj *, common::ObIAllocator> stored_schema_objs_;
common::ObBitSet<> must_be_positive_idx_;
stmt::StmtType stmt_type_;
//*********** for user-defined rules **************
DynamicParamInfoArray dynamic_param_list_;
/**
* call dbms_udr.create_rule('select ?, 1 from dual', 'select ? + 1, 1 from dual');
* call dbms_udr.create_rule('select ?, 2 from dual', 'select ? + 2, 1 from dual');
*
* template SQL: select ?, ? from dual has the following two constant constraints:
* tpl_sql_const_cons_ : {{idx:1, raw_text:"1"}, {idx:1, raw_text:"2"}}
*
* The following constraints are generated when executing a SQL that does not hit any of the rules:
* SQL: select 4, 5 from dual;
* not_param_info_ : {}
* tpl_sql_const_cons_ : {{idx:1, raw_text:"1"}, {idx:1, raw_text:"2"}}
*
* When executing a SQL that hits a rule, the following constraints are generated:
* SQL: select 4, 1 from dual;
* not_param_info_ : {idx:1, raw_text:"1"}
* tpl_sql_const_cons_ : {{idx:1, raw_text:"1"}, {idx:1, raw_text:"2"}}
*
* So the constant constraint matching rules are as follows:
* 1、First match tpl_sql_const_cons_constraint list
* 2、If it hits, use the hit rule to compare it with not_param_info_, if it is the same
* the match succeeds, otherwise it fails
* 3、If there is no hit, match not_param_info_. if the match is successful
* the result is successful, otherwise it fails
*/
TplSqlConstCons tpl_sql_const_cons_;
//*********** end user-defined rules **************
DISALLOW_COPY_AND_ASSIGN(ObPlanCacheValue);
};

View File

@ -292,6 +292,7 @@ ObPsStmtInfo::ObPsStmtInfo(ObIAllocator *inner_allocator)
num_of_returning_into_(-1),
no_param_sql_(),
is_sensitive_sql_(false),
raw_sql_(),
raw_params_(inner_allocator),
raw_params_idx_(inner_allocator)
@ -321,6 +322,7 @@ ObPsStmtInfo::ObPsStmtInfo(ObIAllocator *inner_allocator,
num_of_returning_into_(-1),
no_param_sql_(),
is_sensitive_sql_(false),
raw_sql_(),
raw_params_(inner_allocator),
raw_params_idx_(inner_allocator)
{
@ -343,6 +345,18 @@ int ObPsStmtInfo::assign_no_param_sql(const common::ObString &no_param_sql)
return ret;
}
int ObPsStmtInfo::assign_raw_sql(const common::ObString &raw_sql)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(allocator_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("allocator is invalid", K(ret));
} else if (OB_FAIL(ObPsSqlUtils::deep_copy_str(*allocator_, raw_sql, raw_sql_))) {
LOG_WARN("deep copy raw sql failed", K(raw_sql), K(ret));
}
return ret;
}
int ObPsStmtInfo::add_fixed_raw_param(const ObPCParam &node)
{
int ret = OB_SUCCESS;
@ -473,6 +487,9 @@ int ObPsStmtInfo::deep_copy(const ObPsStmtInfo &other)
} else if (OB_FAIL(ObPsSqlUtils::deep_copy_str(*allocator_, other.get_no_param_sql(),
no_param_sql_))) {
LOG_WARN("deep copy str failed", K(other), K(ret));
} else if (OB_FAIL(ObPsSqlUtils::deep_copy_str(*allocator_, other.get_raw_sql(),
raw_sql_))) {
LOG_WARN("deep copy str failed", K(other), K(ret));
} else if (OB_FAIL(deep_copy_fixed_raw_params(other.raw_params_idx_, other.raw_params_))) {
LOG_WARN("deep copy fixed raw params failed", K(other), K(ret));
} else if (OB_FAIL(ps_sql_meta_.deep_copy(other.get_ps_sql_meta()))) {
@ -507,6 +524,7 @@ int ObPsStmtInfo::get_convert_size(int64_t &cv_size) const
int64_t convert_size = sizeof(ObPsStmtInfo);
convert_size += ps_sql_.length() + 1;
convert_size += no_param_sql_.length() + 1;
convert_size += raw_sql_.length() + 1;
int64_t meta_convert_size = 0;
int64_t raw_params_size = 0;
if (OB_FAIL(ps_sql_meta_.get_convert_size(meta_convert_size))) {

View File

@ -166,6 +166,7 @@ public:
inline int32_t get_num_of_returning_into() const { return num_of_returning_into_; }
inline void set_is_sensitive_sql(const bool is_sensitive_sql) { is_sensitive_sql_ = is_sensitive_sql; }
inline bool get_is_sensitive_sql() const { return is_sensitive_sql_; }
inline const common::ObString &get_raw_sql() const { return raw_sql_; }
bool is_valid() const;
bool check_erase_inc_ref_count();
@ -174,6 +175,7 @@ public:
int add_param_field(const common::ObField &param);
int add_column_field(const common::ObField &column);
int get_convert_size(int64_t &cv_size) const;
int assign_raw_sql(const common::ObString &raw_sql);
int assign_no_param_sql(const common::ObString &no_param_sql);
int assign_fixed_raw_params(const common::ObIArray<int64_t> &param_idxs,
const common::ObIArray<ObPCParam *> &raw_params);
@ -248,6 +250,7 @@ private:
int32_t num_of_returning_into_;
common::ObString no_param_sql_;
bool is_sensitive_sql_;
common::ObString raw_sql_;
// raw_params_ records constants other than question mark in raw prepare sql
// raw_params_idx_ records the offset of the constants in raw_params_ in param_store
// E.g: prepare stmt from 'select 3 + ? + 2 from dual';
@ -400,6 +403,41 @@ private:
DISALLOW_COPY_AND_ASSIGN(ObPsStmtInfoGuard);
};
struct PsCacheInfoCtx
{
PsCacheInfoCtx()
: param_cnt_(0),
num_of_returning_into_(-1),
is_inner_sql_(false),
is_sensitive_sql_(false),
normalized_sql_(),
raw_sql_(),
no_param_sql_(),
raw_params_(NULL),
fixed_param_idx_(NULL),
stmt_type_(stmt::T_NONE) {}
TO_STRING_KV(K_(param_cnt),
K_(num_of_returning_into),
K_(is_inner_sql),
K_(is_sensitive_sql),
K_(normalized_sql),
K_(raw_sql),
K_(no_param_sql),
K_(stmt_type));
int64_t param_cnt_;
int32_t num_of_returning_into_;
bool is_inner_sql_;
bool is_sensitive_sql_;
common::ObString normalized_sql_;
common::ObString raw_sql_;
common::ObString no_param_sql_;
common::ObIArray<ObPCParam*> *raw_params_;
common::ObIArray<int64_t> *fixed_param_idx_;
stmt::StmtType stmt_type_;
};
} //end of namespace sql
} //end of namespace oceanbase

View File

@ -15,6 +15,7 @@
#include "sql/plan_cache/ob_ps_sql_utils.h"
#include "sql/plan_cache/ob_ps_cache_callback.h"
#include "sql/resolver/cmd/ob_call_procedure_stmt.h"
#include "sql/udr/ob_udr_mgr.h"
#include "share/schema/ob_schema_getter_guard.h"
namespace oceanbase
@ -381,25 +382,22 @@ int ObPsCache::ref_stmt_item(const uint64_t db_id,
return ret;
}
int ObPsCache::get_or_add_stmt_info(const ObResultSet &result,
const ObString &origin_sql,
const ObString &no_param_sql,
const ObIArray<ObPCParam*> &raw_params,
const common::ObIArray<int64_t> &raw_params_idx,
int64_t param_cnt,
int ObPsCache::get_or_add_stmt_info(const PsCacheInfoCtx &info_ctx,
const ObResultSet &result,
ObSchemaGetterGuard &schema_guard,
stmt::StmtType stmt_type,
ObPsStmtItem *ps_item,
ObPsStmtInfo *&ref_ps_info,
int32_t returning_into_parm_num)
ObPsStmtInfo *&ref_ps_info)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(ps_item)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(ret), K(ps_item));
} else if (OB_ISNULL(origin_sql.ptr())) {
} else if (OB_ISNULL(info_ctx.normalized_sql_.ptr())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("origin_sql is null", K(ret), K(ps_item));
LOG_WARN("normalized sql is null", K(ret), K(ps_item));
} else if (OB_ISNULL(info_ctx.raw_params_) || OB_ISNULL(info_ctx.fixed_param_idx_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("param is null", K(ret));
} else if (OB_FAIL(ref_stmt_info(ps_item->get_ps_stmt_id(), ref_ps_info))) {
if (OB_HASH_NOT_EXIST == ret) {
ret = OB_SUCCESS;
@ -407,21 +405,25 @@ int ObPsCache::get_or_add_stmt_info(const ObResultSet &result,
ObArenaAllocator allocator;
ObPsStmtInfo tmp_stmt_info(&allocator);
tmp_stmt_info.assign_sql_key(*ps_item);
tmp_stmt_info.set_stmt_type(stmt_type);
tmp_stmt_info.set_stmt_type(info_ctx.stmt_type_);
tmp_stmt_info.set_ps_item(ps_item);
// calc check_sum with origin_sql
uint64_t ps_stmt_checksum = ob_crc64(origin_sql.ptr(),
origin_sql.length()); // actual is crc32
// calc check_sum with normalized sql
uint64_t ps_stmt_checksum = ob_crc64(info_ctx.normalized_sql_.ptr(),
info_ctx.normalized_sql_.length()); // actual is crc32
tmp_stmt_info.set_ps_stmt_checksum(ps_stmt_checksum);
if (OB_FAIL(schema_guard.get_schema_version(tenant_id_, tenant_version))) {
LOG_WARN("fail to get tenant version", K(ret), K(tenant_id_));
} else if (FALSE_IT(tmp_stmt_info.set_tenant_version(tenant_version))) {
// do nothing
} else if (OB_FAIL(tmp_stmt_info.assign_no_param_sql(no_param_sql))) {
LOG_WARN("fail to assign no param sql", K(ret), K(no_param_sql));
} else if (OB_FAIL(tmp_stmt_info.assign_fixed_raw_params(raw_params_idx, raw_params))) {
LOG_WARN("fail to assign raw params failed", K(raw_params_idx), K(ret));
} else if (OB_FAIL(fill_ps_stmt_info(result, param_cnt, tmp_stmt_info, returning_into_parm_num))) {
} else if (OB_FAIL(tmp_stmt_info.assign_no_param_sql(info_ctx.no_param_sql_))) {
LOG_WARN("fail to assign no param sql", K(ret), K(info_ctx.no_param_sql_));
} else if (OB_FAIL(tmp_stmt_info.assign_raw_sql(info_ctx.raw_sql_))) {
LOG_WARN("fail to assign rule name", K(ret), K(info_ctx.raw_sql_));
} else if (OB_FAIL(tmp_stmt_info.assign_fixed_raw_params(*info_ctx.fixed_param_idx_,
*info_ctx.raw_params_))) {
LOG_WARN("fail to assign raw params failed", KPC(info_ctx.fixed_param_idx_), K(ret));
} else if (OB_FAIL(fill_ps_stmt_info(result, info_ctx.param_cnt_,
tmp_stmt_info, info_ctx.num_of_returning_into_))) {
LOG_WARN("fill ps stmt info failed", K(ret));
} else if (OB_FAIL(add_stmt_info(*ps_item, tmp_stmt_info, ref_ps_info))) {
LOG_WARN("add stmt info failed", K(ret), K(*ps_item), K(tmp_stmt_info));

View File

@ -84,17 +84,11 @@ public:
int get_or_add_stmt_item(const uint64_t db_id,
const common::ObString &ps_sql,
ObPsStmtItem *&ps_item_value);
int get_or_add_stmt_info(const ObResultSet &result,
const ObString &origin_sql,
const common::ObString &no_param_sql,
const ObIArray<ObPCParam*> &raw_params,
const common::ObIArray<int64_t> &raw_params_idx,
int64_t param_cnt,
int get_or_add_stmt_info(const PsCacheInfoCtx &info_ctx,
const ObResultSet &result,
ObSchemaGetterGuard &schema_guard,
stmt::StmtType stmt_type,
ObPsStmtItem *ps_item,
ObPsStmtInfo *&ref_ps_info,
int32_t returning_into_parm_num);
ObPsStmtInfo *&ref_ps_info);
int cache_evict();
int cache_evict_all_ps();

View File

@ -63,6 +63,7 @@ struct TransformTreeCtx
SQL_EXECUTION_MODE mode_;
bool is_project_list_scope_;
int64_t assign_father_level_;
const ObIArray<FixedParamValue> *udr_fixed_params_;
bool ignore_scale_check_;
TransformTreeCtx();
};
@ -123,6 +124,7 @@ TransformTreeCtx::TransformTreeCtx() :
mode_(INVALID_MODE),
is_project_list_scope_(false),
assign_father_level_(ObSqlParameterization::NO_VALUES),
udr_fixed_params_(NULL),
ignore_scale_check_(false)
{
}
@ -138,7 +140,8 @@ int ObSqlParameterization::transform_syntax_tree(ObIAllocator &allocator,
SelectItemParamInfoArray *select_item_param_infos,
ObMaxConcurrentParam::FixParamStore &fixed_param_store,
bool is_transform_outline,
SQL_EXECUTION_MODE execution_mode)
SQL_EXECUTION_MODE execution_mode,
const ObIArray<FixedParamValue> *udr_fixed_params)
{
int ret = OB_SUCCESS;
ObCollationType collation_connection = CS_TYPE_INVALID;
@ -173,6 +176,7 @@ int ObSqlParameterization::transform_syntax_tree(ObIAllocator &allocator,
ctx.paramlized_questionmask_count_ = 0;//used for outline sql限流,
ctx.is_transform_outline_ = is_transform_outline;//used for outline sql限流
ctx.raw_params_ = raw_params;
ctx.udr_fixed_params_ = udr_fixed_params;
ctx.is_project_list_scope_ = false;
ctx.mode_ = execution_mode;
ctx.assign_father_level_ = NO_VALUES;
@ -255,6 +259,23 @@ int ObSqlParameterization::is_fast_parse_const(TransformTreeCtx &ctx)
return ret;
}
bool ObSqlParameterization::is_udr_not_param(TransformTreeCtx &ctx)
{
bool b_ret = false;
if (OB_ISNULL(ctx.tree_) || (NULL == ctx.udr_fixed_params_)) {
b_ret = false;
} else {
for (int64_t i = 0; !b_ret && i < ctx.udr_fixed_params_->count(); ++i) {
const FixedParamValue &fixed_param = ctx.udr_fixed_params_->at(i);
if (fixed_param.idx_ == ctx.tree_->raw_param_idx_) {
b_ret = true;
break;
}
}
}
return b_ret;
}
//判断该node是否为不能参数化的node
bool ObSqlParameterization::is_node_not_param(TransformTreeCtx &ctx)
{
@ -598,9 +619,11 @@ int ObSqlParameterization::transform_tree(TransformTreeCtx &ctx,
//do nothing
} else if (!is_execute_mode(ctx.mode_) && OB_FAIL(ctx.params_->push_back(value))) {
SQL_PC_LOG(WARN, "fail to push into params", K(ret));
} else if (is_udr_not_param(ctx) && OB_FAIL(add_not_param_flag(ctx.tree_, *ctx.sql_info_))) {
SQL_PC_LOG(WARN, "fail to add not param flag", K(ret));
}
}
} else if (add_not_param_flag(ctx.tree_, *ctx.sql_info_)) { //not param
} else if (OB_FAIL(add_not_param_flag(ctx.tree_, *ctx.sql_info_))) { //not param
SQL_PC_LOG(WARN, "fail to add not param flag", K(ret));
}
} //if is_fast_parse_const end
@ -906,11 +929,14 @@ int ObSqlParameterization::parameterize_syntax_tree(common::ObIAllocator &alloca
// if so, faster parser is needed
// otherwise, fast parser has been done before
pc_ctx.fp_result_.reset();
FPContext fp_ctx(cs_type);
fp_ctx.enable_batched_multi_stmt_ = pc_ctx.sql_ctx_.handle_batched_multi_stmt();
fp_ctx.sql_mode_ = session->get_sql_mode();
fp_ctx.is_udr_mode_ = pc_ctx.is_rewrite_sql_;
fp_ctx.def_name_ctx_ = pc_ctx.def_name_ctx_;
if (OB_FAIL(fast_parser(allocator,
session->get_sql_mode(),
cs_type,
fp_ctx,
pc_ctx.raw_sql_,
pc_ctx.sql_ctx_.handle_batched_multi_stmt(),
pc_ctx.fp_result_))) {
SQL_PC_LOG(WARN, "fail to fast parser", K(ret));
}
@ -925,14 +951,15 @@ int ObSqlParameterization::parameterize_syntax_tree(common::ObIAllocator &alloca
LOG_WARN("failed to reserve array", K(ret));
} else if (OB_FAIL(transform_syntax_tree(allocator,
*session,
&pc_ctx.fp_result_.raw_params_,
is_execute_mode(mode) ? NULL : &pc_ctx.fp_result_.raw_params_,
tree,
sql_info,
params,
is_prepare_mode(mode) ? NULL : &pc_ctx.select_item_param_infos_,
fix_param_store,
is_transform_outline,
mode))) {
mode,
&pc_ctx.fixed_param_info_list_))) {
if (OB_NOT_SUPPORTED != ret) {
SQL_PC_LOG(WARN, "fail to normal parameterized parser tree", K(ret));
}
@ -1224,10 +1251,8 @@ bool ObSqlParameterization::need_fast_parser(const ObString &sql)
}
int ObSqlParameterization::fast_parser(ObIAllocator &allocator,
ObSQLMode sql_mode,
ObCollationType connection_collation,
const FPContext &fp_ctx,
const ObString &sql,
const bool enable_batched_multi_stmt,
ObFastParserResult &fp_result)
{
//UNUSED(sql_mode);
@ -1242,8 +1267,8 @@ int ObSqlParameterization::fast_parser(ObIAllocator &allocator,
|| (ObParser::is_pl_stmt(sql, nullptr, &is_call_procedure) && !is_call_procedure))) {
(void)fp_result.pc_key_.name_.assign_ptr(sql.ptr(), sql.length());
} else if (GCONF._ob_enable_fast_parser) {
if (OB_FAIL(ObFastParser::parse(sql, enable_batched_multi_stmt, no_param_sql_ptr,
no_param_sql_len, p_list, param_num, connection_collation, allocator, sql_mode))) {
if (OB_FAIL(ObFastParser::parse(sql, fp_ctx, allocator, no_param_sql_ptr,
no_param_sql_len, p_list, param_num, fp_result.question_mark_ctx_))) {
LOG_WARN("fast parse error", K(param_num),
K(ObString(no_param_sql_len, no_param_sql_ptr)), K(sql));
}
@ -1252,6 +1277,7 @@ int ObSqlParameterization::fast_parser(ObIAllocator &allocator,
if (param_num > 0) {
ObPCParam *pc_param = NULL;
char *ptr = (char *)allocator.alloc(param_num * sizeof(ObPCParam));
fp_result.raw_params_.reset();
fp_result.raw_params_.set_allocator(&allocator);
fp_result.raw_params_.set_capacity(param_num);
if (OB_ISNULL(ptr)) {
@ -1271,9 +1297,9 @@ int ObSqlParameterization::fast_parser(ObIAllocator &allocator,
} else { /*do nothing*/}
}
} else {
ObParser parser(allocator, sql_mode, connection_collation);
ObParser parser(allocator, fp_ctx.sql_mode_, fp_ctx.conn_coll_);
SMART_VAR(ParseResult, parse_result) {
if (OB_FAIL(parser.parse(sql, parse_result, FP_MODE, enable_batched_multi_stmt))) {
if (OB_FAIL(parser.parse(sql, parse_result, FP_MODE, fp_ctx.enable_batched_multi_stmt_))) {
SQL_PC_LOG(WARN, "fail to fast parser", K(sql), K(ret));
} else {
(void)fp_result.pc_key_.name_.assign_ptr(parse_result.no_param_sql_, parse_result.no_param_sql_len_);

View File

@ -21,6 +21,7 @@
#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"
@ -115,10 +116,8 @@ public:
ObSqlParameterization() {}
virtual ~ObSqlParameterization() {}
static int fast_parser(common::ObIAllocator &allocator,
ObSQLMode sql_mode,
common::ObCollationType connection_collation,
const FPContext &fp_ctx,
const common::ObString &sql,
const bool enable_batched_multi_stmt,
ObFastParserResult &fp_result);
static int transform_syntax_tree(common::ObIAllocator &allocator,
@ -130,7 +129,8 @@ public:
SelectItemParamInfoArray *select_item_param_infos,
share::schema::ObMaxConcurrentParam::FixParamStore &fixed_param_store,
bool is_transform_outline,
SQL_EXECUTION_MODE execution_mode = INVALID_MODE);
SQL_EXECUTION_MODE execution_mode = INVALID_MODE,
const ObIArray<FixedParamValue> *udr_fixed_params = NULL);
static int raw_fast_parameterize_sql(common::ObIAllocator &allocator,
const ObSQLSessionInfo &session,
const common::ObString &sql,
@ -170,6 +170,7 @@ private:
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);