[FEAT MERGE]:develop pl feature of 4.2 version
Co-authored-by: LiuYoung00 <liuyanglo_ol@163.com> Co-authored-by: 0xacc <heyongyi1998@gmail.com> Co-authored-by: seuwebber <webber_code@163.com>
This commit is contained in:
parent
8e9c9d0c5f
commit
57f1c6e7ee
@ -39,6 +39,7 @@ ob_set_subtarget(ob_pl common
|
||||
ob_set_subtarget(ob_pl common_mixed
|
||||
pl_cache/ob_pl_cache.cpp
|
||||
pl_cache/ob_pl_cache_mgr.cpp
|
||||
pl_cache/ob_pl_cache_object.cpp
|
||||
)
|
||||
|
||||
ob_set_subtarget(ob_pl sys_package
|
||||
|
130
src/pl/ob_pl.cpp
130
src/pl/ob_pl.cpp
@ -966,36 +966,43 @@ int ObPLContext::set_role_id_array(ObPLFunction &routine,
|
||||
|
||||
if (ObSchemaChecker::is_ora_priv_check() && !routine.is_invoker_right()
|
||||
&& routine.get_proc_type() != STANDALONE_ANONYMOUS) {
|
||||
uint64_t priv_user_id = OB_INVALID_ID;
|
||||
CK (OB_NOT_NULL(session_info_));
|
||||
/* 1. save in definer, just for more information */
|
||||
OX (old_in_definer_ = session_info_->get_in_definer_named_proc());
|
||||
OX (session_info_->set_in_definer_named_proc(true));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (0 == session_info_->get_database_name().case_compare(OB_SYS_DATABASE_NAME)) {
|
||||
OX (priv_user_id = OB_ORA_SYS_USER_ID);
|
||||
} else {
|
||||
OZ (guard.get_user_id(session_info_->get_effective_tenant_id(),
|
||||
session_info_->get_database_name(),
|
||||
ObString(OB_DEFAULT_HOST_NAME),
|
||||
priv_user_id,
|
||||
false));
|
||||
bool is_special_ir = false;
|
||||
if (OB_FAIL(routine.is_special_pkg_invoke_right(guard, is_special_ir))){
|
||||
LOG_WARN("failed to check special pkg invoke right", K(ret));
|
||||
} else if (is_special_ir){
|
||||
need_reset_role_id_array_ = false;
|
||||
} else {
|
||||
uint64_t priv_user_id = OB_INVALID_ID;
|
||||
CK (OB_NOT_NULL(session_info_));
|
||||
/* 1. save in definer, just for more information */
|
||||
OX (old_in_definer_ = session_info_->get_in_definer_named_proc());
|
||||
OX (session_info_->set_in_definer_named_proc(true));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (0 == session_info_->get_database_name().case_compare(OB_SYS_DATABASE_NAME)) {
|
||||
OX (priv_user_id = OB_ORA_SYS_USER_ID);
|
||||
} else {
|
||||
OZ (guard.get_user_id(session_info_->get_effective_tenant_id(),
|
||||
session_info_->get_database_name(),
|
||||
ObString(OB_DEFAULT_HOST_NAME),
|
||||
priv_user_id,
|
||||
false));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && OB_INVALID_ID == priv_user_id) {
|
||||
ret = OB_USER_NOT_EXIST;
|
||||
LOG_WARN("fail to get procedure owner id",
|
||||
K(session_info_->get_effective_tenant_id()),
|
||||
K(session_info_->get_database_name()));
|
||||
}
|
||||
/* 2. save priv user id, and set new priv user id, change grantee_id, for priv check */
|
||||
OX (old_priv_user_id_ = session_info_->get_priv_user_id());
|
||||
OX (session_info_->set_priv_user_id(priv_user_id));
|
||||
/* 3. save role id array , remove role id array for priv check */
|
||||
OZ (old_role_id_array_.assign(session_info_->get_enable_role_array()));
|
||||
OX (session_info_->get_enable_role_array().reset());
|
||||
OZ (session_info_->get_enable_role_array().push_back(OB_ORA_PUBLIC_ROLE_ID));
|
||||
OX (need_reset_role_id_array_ = true);
|
||||
}
|
||||
if (OB_SUCC(ret) && OB_INVALID_ID == priv_user_id) {
|
||||
ret = OB_USER_NOT_EXIST;
|
||||
LOG_WARN("fail to get procedure owner id",
|
||||
K(session_info_->get_effective_tenant_id()),
|
||||
K(session_info_->get_database_name()));
|
||||
}
|
||||
/* 2. save priv user id, and set new priv user id, change grantee_id, for priv check */
|
||||
OX (old_priv_user_id_ = session_info_->get_priv_user_id());
|
||||
OX (session_info_->set_priv_user_id(priv_user_id));
|
||||
/* 3. save role id array , remove role id array for priv check */
|
||||
OZ (old_role_id_array_.assign(session_info_->get_enable_role_array()));
|
||||
OX (session_info_->get_enable_role_array().reset());
|
||||
OZ (session_info_->get_enable_role_array().push_back(OB_ORA_PUBLIC_ROLE_ID));
|
||||
OX (need_reset_role_id_array_ = true);
|
||||
} else if (lib::is_mysql_mode() && !routine.is_invoker_right() &&
|
||||
0 != routine.get_priv_user().length()
|
||||
/* 兼容存量存储过程,存量存储过程的priv_user为空。mysql存储过程默认为definer行为,
|
||||
@ -3451,59 +3458,6 @@ ObPLCompileUnit::~ObPLCompileUnit()
|
||||
}
|
||||
}
|
||||
|
||||
void ObPLCompileUnit::reset()
|
||||
{
|
||||
ObILibCacheObject::reset();
|
||||
tenant_schema_version_ = OB_INVALID_VERSION;
|
||||
sys_schema_version_ = OB_INVALID_VERSION;
|
||||
dependency_tables_.reset();
|
||||
params_info_.reset();
|
||||
}
|
||||
|
||||
int ObPLCompileUnit::set_params_info(const ParamStore ¶ms)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t N = params.count();
|
||||
ObParamInfo param_info;
|
||||
if (N > 0 && OB_FAIL(params_info_.reserve(N))) {
|
||||
OB_LOG(WARN, "fail to reserve params info", K(ret));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
|
||||
param_info.flag_ = params.at(i).get_param_flag();
|
||||
param_info.type_ = params.at(i).get_param_meta().get_type();
|
||||
param_info.col_type_ = params.at(i).get_collation_type();
|
||||
if (ObSQLUtils::is_oracle_empty_string(params.at(i))) {
|
||||
param_info.is_oracle_empty_string_ = true;
|
||||
}
|
||||
if (params.at(i).get_param_meta().get_type() != params.at(i).get_type()) {
|
||||
LOG_TRACE("differ in set_params_info",
|
||||
K(params.at(i).get_param_meta().get_type()),
|
||||
K(params.at(i).get_type()),
|
||||
K(common::lbt()));
|
||||
}
|
||||
//todo:it is for arraybinding check, not pl ext check
|
||||
if (params.at(i).is_ext()) {
|
||||
ObDataType data_type;
|
||||
if (OB_FAIL(ObSQLUtils::get_ext_obj_data_type(params.at(i), data_type))) {
|
||||
LOG_WARN("fail to get ext obj data type", K(ret));
|
||||
} else {
|
||||
param_info.ext_real_type_ = data_type.get_obj_type();
|
||||
param_info.scale_ = data_type.get_meta_type().get_scale();
|
||||
}
|
||||
LOG_DEBUG("ext params info", K(data_type), K(param_info), K(params.at(i)));
|
||||
} else {
|
||||
param_info.scale_ = params.at(i).get_scale();
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(params_info_.push_back(param_info))) {
|
||||
LOG_WARN("failed to push back param info", K(ret));
|
||||
}
|
||||
}
|
||||
param_info.reset();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLCompileUnit::add_routine(ObPLFunction *routine)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -3526,6 +3480,14 @@ int ObPLCompileUnit::get_routine(int64_t routine_idx, ObPLFunction *&routine) co
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObPLCompileUnit::reset()
|
||||
{
|
||||
ObPLCacheObject::reset();
|
||||
tenant_schema_version_ = OB_INVALID_VERSION;
|
||||
sys_schema_version_ = OB_INVALID_VERSION;
|
||||
dependency_tables_.reset();
|
||||
}
|
||||
|
||||
|
||||
int ObPLCompileUnit::check_need_add_cache_obj_stat(ObILibCacheCtx &ctx, bool &need_real_add)
|
||||
{
|
||||
@ -3771,12 +3733,14 @@ int ObPLFunction::is_special_pkg_invoke_right(ObSchemaGetterGuard &guard, bool &
|
||||
static const char *name_pair[] = { "dbms_utility", "name_resolve" };
|
||||
static const char *name_pair1[] = { "dbms_utility", "ICD_NAME_RES" };
|
||||
static const char *name_pair2[] = { "dbms_utility", "old_current_schema" };
|
||||
static const char *name_pair3[] = { "dbms_describe", "describe_procedure" };
|
||||
static const char *name_pair3[] = { "dbms_utility", "exec_ddl_statement" };
|
||||
static const char *name_pair4[] = { "dbms_describe", "describe_procedure" };
|
||||
static name_pair_ptr name_arr[] = {
|
||||
&name_pair,
|
||||
&name_pair1,
|
||||
&name_pair2,
|
||||
&name_pair3
|
||||
&name_pair3,
|
||||
&name_pair4
|
||||
// { "dbms_utility", "name_resolve" }
|
||||
};
|
||||
int ret = OB_SUCCESS;
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "pl/ob_pl_interface_pragma.h"
|
||||
#include "sql/plan_cache/ob_cache_object_factory.h"
|
||||
#include "pl/pl_cache/ob_pl_cache.h"
|
||||
#include "pl/pl_cache/ob_pl_cache_object.h"
|
||||
|
||||
namespace test
|
||||
{
|
||||
@ -260,27 +261,17 @@ private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObPLFunctionBase);
|
||||
};
|
||||
|
||||
class ObPLCompileUnit : public sql::ObILibCacheObject
|
||||
class ObPLCompileUnit : public ObPLCacheObject
|
||||
{
|
||||
friend class ::test::MockCacheObjectFactory;
|
||||
public:
|
||||
ObPLCompileUnit(sql::ObLibCacheNameSpace ns, lib::MemoryContext &mem_context)
|
||||
: ObILibCacheObject(ns, mem_context),
|
||||
tenant_schema_version_(OB_INVALID_VERSION),
|
||||
sys_schema_version_(OB_INVALID_VERSION),
|
||||
dependency_tables_(allocator_),
|
||||
params_info_( (ObWrapperAllocator(allocator_)) ),
|
||||
: ObPLCacheObject(ns, mem_context),
|
||||
routine_table_(allocator_),
|
||||
type_table_(),
|
||||
expr_factory_(allocator_),
|
||||
helper_(allocator_),
|
||||
di_helper_(allocator_),
|
||||
sql_expression_factory_(allocator_),
|
||||
expr_operator_factory_(allocator_),
|
||||
expressions_(allocator_),
|
||||
expr_op_size_(0),
|
||||
can_cached_(true),
|
||||
frame_info_(allocator_)
|
||||
can_cached_(true)
|
||||
{
|
||||
#ifndef USE_MCJIT
|
||||
helper_.init();
|
||||
@ -288,20 +279,6 @@ public:
|
||||
}
|
||||
virtual ~ObPLCompileUnit();
|
||||
|
||||
inline int64_t get_dependency_table_size() const { return dependency_tables_.count(); }
|
||||
inline const DependenyTableStore &get_dependency_table() const { return dependency_tables_; }
|
||||
inline void set_sys_schema_version(int64_t schema_version) { sys_schema_version_ = schema_version; }
|
||||
inline void set_tenant_schema_version(int64_t schema_version) { tenant_schema_version_ = schema_version; }
|
||||
inline int64_t get_tenant_schema_version() const { return tenant_schema_version_; }
|
||||
inline int64_t get_sys_schema_version() const { return sys_schema_version_; }
|
||||
int init_dependency_table_store(int64_t dependency_table_cnt) { return dependency_tables_.init(dependency_table_cnt); }
|
||||
inline DependenyTableStore &get_dependency_table() { return dependency_tables_; }
|
||||
|
||||
int set_params_info(const ParamStore ¶ms);
|
||||
const common::Ob2DArray<ObParamInfo,
|
||||
common::OB_MALLOC_BIG_BLOCK_SIZE,
|
||||
common::ObWrapperAllocator, false> &get_params_info() const { return params_info_; }
|
||||
|
||||
inline bool get_can_cached() { return can_cached_; }
|
||||
inline void set_can_cached(bool can_cached) { can_cached_ = can_cached; }
|
||||
inline const ObIArray<ObPLFunction*> &get_routine_table() const { return routine_table_; }
|
||||
@ -314,54 +291,29 @@ public:
|
||||
int get_routine(int64_t routine_idx, ObPLFunction *&routine) const;
|
||||
void init_routine_table(int64_t count) { routine_table_.set_capacity(static_cast<uint32_t>(count)); }
|
||||
inline const ObIArray<ObUserDefinedType *> &get_type_table() const { return type_table_; }
|
||||
inline sql::ObRawExprFactory &get_expr_factory() { return expr_factory_; }
|
||||
|
||||
inline jit::ObLLVMHelper &get_helper() { return helper_; }
|
||||
inline jit::ObLLVMDIHelper &get_di_helper() { return di_helper_; }
|
||||
|
||||
inline sql::ObSqlExpressionFactory &get_sql_expression_factory() { return sql_expression_factory_; }
|
||||
inline sql::ObExprOperatorFactory &get_expr_operator_factory() { return expr_operator_factory_; }
|
||||
inline const common::ObIArray<sql::ObSqlExpression*> &get_expressions() const { return expressions_; }
|
||||
inline common::ObIArray<sql::ObSqlExpression*> &get_expressions() { return expressions_; }
|
||||
inline int set_expressions(common::ObIArray<sql::ObSqlExpression*> &exprs) { return expressions_.assign(exprs); }
|
||||
inline int64_t get_expr_op_size() const { return expr_op_size_; }
|
||||
inline void set_expr_op_size(int64_t size) { expr_op_size_ = size; }
|
||||
inline sql::ObExprFrameInfo &get_frame_info() { return frame_info_; }
|
||||
jit::ObDIRawData get_debug_info() const { return helper_.get_debug_info(); }
|
||||
|
||||
virtual void reset();
|
||||
virtual void dump_deleted_log_info(const bool is_debug_log = true) const;
|
||||
virtual int check_need_add_cache_obj_stat(ObILibCacheCtx &ctx, bool &need_real_add);
|
||||
|
||||
TO_STRING_KV(K_(routine_table), K(expr_op_size_), K_(can_cached),
|
||||
TO_STRING_KV(K_(routine_table), K_(can_cached),
|
||||
K_(tenant_schema_version), K_(sys_schema_version));
|
||||
|
||||
protected:
|
||||
int64_t tenant_schema_version_;
|
||||
int64_t sys_schema_version_;
|
||||
DependenyTableStore dependency_tables_;
|
||||
|
||||
//stored args information after paramalization
|
||||
common::Ob2DArray<ObParamInfo,
|
||||
common::OB_MALLOC_BIG_BLOCK_SIZE,
|
||||
common::ObWrapperAllocator, false> params_info_;
|
||||
|
||||
common::ObFixedArray<ObPLFunction*, common::ObIAllocator> routine_table_;
|
||||
common::ObArray<ObUserDefinedType *> type_table_;
|
||||
sql::ObRawExprFactory expr_factory_;
|
||||
|
||||
jit::ObLLVMHelper helper_;
|
||||
jit::ObLLVMDIHelper di_helper_;
|
||||
|
||||
sql::ObSqlExpressionFactory sql_expression_factory_;
|
||||
sql::ObExprOperatorFactory expr_operator_factory_;
|
||||
common::ObFixedArray<sql::ObSqlExpression*, common::ObIAllocator> expressions_;
|
||||
int64_t expr_op_size_;
|
||||
|
||||
bool can_cached_;
|
||||
|
||||
sql::ObExprFrameInfo frame_info_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ObPLCompileUnit);
|
||||
};
|
||||
|
||||
|
@ -1149,7 +1149,6 @@ int ObPLCodeGenerateVisitor::visit(const ObPLCursorForLoopStmt &s)
|
||||
s.get_index(),
|
||||
static_cast<int64_t>(INT64_MAX),
|
||||
s.get_user_type(),
|
||||
s.get_expand_user_types(),
|
||||
ret_err));
|
||||
OZ (generator_.get_helper().create_icmp_eq(ret_err, OB_READ_NOTHING, is_not_found));
|
||||
OZ (generator_.get_helper().stack_restore(stack));
|
||||
@ -1645,7 +1644,7 @@ int ObPLCodeGenerateVisitor::visit(const ObPLExecuteStmt &s)
|
||||
ObLLVMValue exprs_not_null_array_value;
|
||||
ObLLVMValue pl_integer_range_array_value;
|
||||
ObLLVMValue is_bulk;
|
||||
ObLLVMValue is_returning;
|
||||
ObLLVMValue is_returning, is_type_record;
|
||||
ObLLVMValue ret_err;
|
||||
|
||||
OZ (generator_.get_helper().set_insert_point(generator_.get_current()));
|
||||
@ -1738,6 +1737,8 @@ int ObPLCodeGenerateVisitor::visit(const ObPLExecuteStmt &s)
|
||||
OZ (args.push_back(is_bulk));
|
||||
OZ (generator_.get_helper().get_int8(s.get_is_returning(), is_returning));
|
||||
OZ (args.push_back(is_returning));
|
||||
OZ (generator_.get_helper().get_int8(s.is_type_record(), is_type_record));
|
||||
OZ (args.push_back(is_type_record));
|
||||
|
||||
// execution
|
||||
OZ (generator_.get_helper().create_call(
|
||||
@ -2735,7 +2736,6 @@ int ObPLCodeGenerateVisitor::visit(const ObPLFetchStmt &s)
|
||||
s.get_index(),
|
||||
s.get_limit(),
|
||||
s.get_user_type(),
|
||||
s.get_expand_user_types(),
|
||||
ret_err))) {
|
||||
LOG_WARN("failed to generate fetch", K(ret));
|
||||
} else if (lib::is_mysql_mode()) { //Mysql模式直接检查抛出异常
|
||||
@ -3048,6 +3048,100 @@ int ObPLCodeGenerateVisitor::visit(const ObPLDoStmt &s)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLCodeGenerateVisitor::visit(const ObPLCaseStmt &s)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (NULL == generator_.get_current().get_v()) {
|
||||
//控制流已断,后面的语句不再处理
|
||||
} else if (OB_FAIL(generator_.get_helper().set_insert_point(generator_.get_current()))) {
|
||||
LOG_WARN("failed to set insert point", K(ret));
|
||||
} else if (OB_FAIL(generator_.set_debug_location(s))) {
|
||||
LOG_WARN("failed to set debug location", K(ret));
|
||||
} else if (OB_FAIL(generator_.generate_goto_label(s))) {
|
||||
LOG_WARN("failed to generate goto label", K(ret));
|
||||
} else {
|
||||
// generate case expr, if any
|
||||
if (s.get_case_expr() != OB_INVALID_ID) {
|
||||
int64_t case_expr_idx = s.get_case_expr();
|
||||
int64_t case_var_idx = s.get_case_var();
|
||||
ObLLVMValue p_result_obj;
|
||||
if (OB_FAIL(generator_.generate_expr(case_expr_idx, s, case_var_idx, p_result_obj))) {
|
||||
LOG_WARN("failed to generate calc_expr func", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
// generate when clause
|
||||
ObLLVMBasicBlock continue_branch;
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(generator_.get_helper().create_block(
|
||||
ObString("continue"), generator_.get_func(), continue_branch))) {
|
||||
LOG_WARN("faild to create continue branch for case stmt", K(ret));
|
||||
} else {
|
||||
const ObPLCaseStmt::WhenClauses &when = s.get_when_clauses();
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < when.count(); ++i) {
|
||||
const ObPLCaseStmt::WhenClause ¤t_when = when.at(i);
|
||||
const sql::ObRawExpr *expr = s.get_expr(current_when.expr_);
|
||||
ObLLVMBasicBlock current_then;
|
||||
ObLLVMBasicBlock current_else;
|
||||
ObLLVMValue p_cond;
|
||||
ObLLVMValue cond;
|
||||
ObLLVMValue is_false;
|
||||
if (OB_ISNULL(expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected nullptr to when expr", K(i), K(current_when));
|
||||
} else if (OB_FAIL(generator_.get_helper().create_block(
|
||||
ObString("then"), generator_.get_func(), current_then))) {
|
||||
LOG_WARN("failed to create then branch for case stmt", K(ret));
|
||||
} else if (OB_FAIL(generator_.get_helper().create_block(
|
||||
ObString("else"), generator_.get_func(), current_else))) {
|
||||
LOG_WARN("failed to create else branch for case stmt", K(ret));
|
||||
} else if (OB_FAIL(generator_.generate_expr(
|
||||
current_when.expr_, s, OB_INVALID_INDEX, p_cond))) {
|
||||
LOG_WARN("failed to generate calc_expr func", K(ret));
|
||||
} else if (OB_FAIL(generator_.extract_value_from_objparam(
|
||||
p_cond, expr->get_data_type(), cond))) {
|
||||
LOG_WARN("failed to extract_value_from_objparam", K(ret));
|
||||
} else if (OB_FAIL(generator_.get_helper().create_icmp_eq(
|
||||
cond, FALSE, is_false))) {
|
||||
LOG_WARN("failed to create_icmp_eq", K(ret));
|
||||
} else if (OB_FAIL(generator_.get_helper().create_cond_br(
|
||||
is_false, current_else, current_then))) {
|
||||
LOG_WARN("failed to create_cond_br", K(ret));
|
||||
} else if (OB_FAIL(generator_.set_current(current_then))) {
|
||||
LOG_WARN("failed to set current to current_then branch", K(ret));
|
||||
} else if (OB_FAIL(visit(*current_when.body_))) {
|
||||
LOG_WARN("failed to visit then clause for case stmt", K(ret));
|
||||
} else if (OB_FAIL(generator_.finish_current(continue_branch))) {
|
||||
LOG_WARN("failed to finish current", K(ret));
|
||||
} else if (OB_FAIL(generator_.set_current(current_else))) {
|
||||
LOG_WARN("failed to set current to current_else branch", K(ret));
|
||||
} else {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// generate else
|
||||
if (OB_SUCC(ret)) {
|
||||
const ObPLStmtBlock *else_clause = s.get_else_clause();
|
||||
if (OB_ISNULL(else_clause)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("else in CASE stmt is NULL in CG", K(s), K(ret));
|
||||
} else if (OB_FAIL(visit(*else_clause))) {
|
||||
LOG_WARN("failed to visit else clause for case stmt", K(ret));
|
||||
} else if (OB_FAIL(generator_.finish_current(continue_branch))) {
|
||||
LOG_WARN("failed to finish current", K(ret));
|
||||
} else if (OB_FAIL(generator_.set_current(continue_branch))) {
|
||||
LOG_WARN("failed to set current", K(ret));
|
||||
} else {
|
||||
// do nohting
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLCodeGenerateVisitor::find_next_procedence_condition(common::ObIArray<std::pair<ObPLConditionType, int64_t>> &conditions,
|
||||
common::ObIArray<int64_t> &position_map, int64_t &idx)
|
||||
{
|
||||
@ -3394,6 +3488,8 @@ int ObPLCodeGenerator::init_spi_service()
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(arg_types.push_back(bool_type))) {
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(arg_types.push_back(bool_type))) {
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(ObLLVMFunctionType::get(int32_type, arg_types, ft))) {
|
||||
LOG_WARN("failed to get function type", K(ret));
|
||||
} else if (OB_FAIL(helper_.create_function(ObString("spi_set_variable"), ft, spi_service_.spi_set_variable_))) {
|
||||
@ -3425,6 +3521,8 @@ int ObPLCodeGenerator::init_spi_service()
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(arg_types.push_back(bool_type))) {
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(arg_types.push_back(bool_type))) {
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(ObLLVMFunctionType::get(int32_type, arg_types, ft))) {
|
||||
LOG_WARN("failed to get function type", K(ret));
|
||||
} else if (OB_FAIL(helper_.create_function(ObString("spi_query"), ft, spi_service_.spi_query_))) {
|
||||
@ -3471,6 +3569,8 @@ int ObPLCodeGenerator::init_spi_service()
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(arg_types.push_back(bool_type))) {
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(arg_types.push_back(bool_type))) {
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(ObLLVMFunctionType::get(int32_type, arg_types, ft))) {
|
||||
LOG_WARN("failed to get function type", K(ret));
|
||||
} else if (OB_FAIL(helper_.create_function(ObString("spi_execute"), ft, spi_service_.spi_execute_))) {
|
||||
@ -3506,6 +3606,8 @@ int ObPLCodeGenerator::init_spi_service()
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(arg_types.push_back(bool_type))) {
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(arg_types.push_back(bool_type))) {
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(ObLLVMFunctionType::get(int32_type, arg_types, ft))) {
|
||||
LOG_WARN("failed to get function type", K(ret));
|
||||
} else if (OB_FAIL(helper_.create_function(ObString("spi_execute_immediate"), ft, spi_service_.spi_execute_immediate_))) {
|
||||
@ -3661,6 +3763,7 @@ int ObPLCodeGenerator::init_spi_service()
|
||||
OZ (arg_types.push_back(int64_type));//limit
|
||||
OZ (arg_types.push_back(data_type_pointer_type));//return_type
|
||||
OZ (arg_types.push_back(int64_type));//return_type_count
|
||||
OZ (arg_types.push_back(bool_type));//is_type_record
|
||||
OZ (ObLLVMFunctionType::get(int32_type, arg_types, ft));
|
||||
OZ (helper_.create_function(ObString("spi_cursor_fetch"), ft, spi_service_.spi_cursor_fetch_));
|
||||
}
|
||||
@ -4621,7 +4724,6 @@ int ObPLCodeGenerator::generate_fetch(const ObPLStmt &s,
|
||||
const int64_t &cursor_index,
|
||||
const int64_t &limit,
|
||||
const ObUserDefinedType *user_defined_type,
|
||||
const ObIArray<ObDataType> &user_types,
|
||||
jit::ObLLVMValue &ret_err)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -4651,7 +4753,7 @@ int ObPLCodeGenerator::generate_fetch(const ObPLStmt &s,
|
||||
ObLLVMValue type_count_value;
|
||||
ObLLVMValue exprs_not_null_array_value;
|
||||
ObLLVMValue pl_integer_array_value;
|
||||
ObLLVMValue is_bulk;
|
||||
ObLLVMValue is_bulk, is_type_record;
|
||||
OZ (generate_into(into, into_array_value, into_count_value,
|
||||
type_array_value, type_count_value,
|
||||
exprs_not_null_array_value,
|
||||
@ -4709,31 +4811,46 @@ int ObPLCodeGenerator::generate_fetch(const ObPLStmt &s,
|
||||
OZ (ObLLVMHelper::get_null_const(data_type_pointer, return_type_array_value));
|
||||
OZ (helper_.get_int64(0, return_type_count_value));
|
||||
} else {
|
||||
const ObRecordType *return_type = static_cast<const ObRecordType*>(user_defined_type);
|
||||
const ObPLDataType *pl_data_type = nullptr;
|
||||
CK (OB_NOT_NULL(return_type));
|
||||
OZ (adt_service_.get_data_type(data_type));
|
||||
OZ (data_type.get_pointer_to(data_type_pointer));
|
||||
OZ (ObLLVMHelper::get_array_type(data_type,
|
||||
user_types.count(),
|
||||
return_type->get_record_member_count(),
|
||||
array_type));
|
||||
OZ (helper_.create_alloca(ObString("datatype_array"),
|
||||
array_type,
|
||||
return_type_array_value));
|
||||
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < user_types.count(); ++i) {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < return_type->get_record_member_count(); ++i) {
|
||||
type_value.reset();
|
||||
OZ (helper_.create_gep(ObString("extract_datatype"),
|
||||
return_type_array_value,
|
||||
i, type_value));
|
||||
OZ (store_data_type(user_types.at(i), type_value));
|
||||
pl_data_type = return_type->get_record_member_type(i);
|
||||
CK (OB_NOT_NULL(pl_data_type));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (pl_data_type->is_obj_type()) {
|
||||
OZ (store_data_type(*(pl_data_type->get_data_type()), type_value));
|
||||
} else { // 构造函数场景
|
||||
ObDataType ext_type;
|
||||
ext_type.set_obj_type(ObExtendType);
|
||||
OZ (store_data_type(ext_type, type_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OZ (helper_.create_bit_cast(ObString("datatype_array_to_pointer"),
|
||||
return_type_array_value, data_type_pointer, return_type_array_value));
|
||||
OZ (helper_.get_int64(static_cast<int64_t>(user_types.count()),
|
||||
OZ (helper_.get_int64(static_cast<int64_t>(return_type->get_record_member_count()),
|
||||
return_type_count_value));
|
||||
}
|
||||
|
||||
OZ (args.push_back(return_type_array_value));
|
||||
OZ (args.push_back(return_type_count_value));
|
||||
OZ (helper_.get_int8(static_cast<int64_t>(into.is_type_record()), is_type_record));
|
||||
OZ (args.push_back(is_type_record));
|
||||
|
||||
OZ (get_helper().create_call(ObString("spi_cursor_fetch"),
|
||||
get_spi_service().spi_cursor_fetch_,
|
||||
@ -5157,7 +5274,7 @@ int ObPLCodeGenerator::generate_sql(const ObPLSqlStmt &s, ObLLVMValue &ret_err)
|
||||
ObLLVMValue for_update;
|
||||
ObLLVMValue hidden_rowid;
|
||||
ObLLVMValue params;
|
||||
ObLLVMValue count;
|
||||
ObLLVMValue count, is_type_record;
|
||||
OZ (args.push_back(get_vars().at(CTX_IDX)));
|
||||
OZ (generate_sql(s, str, len, ps_sql, type, for_update, hidden_rowid, params, count));
|
||||
if (OB_SUCC(ret)) {
|
||||
@ -5194,12 +5311,16 @@ int ObPLCodeGenerator::generate_sql(const ObPLSqlStmt &s, ObLLVMValue &ret_err)
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (s.get_params().empty()) {
|
||||
OZ (get_helper().get_int8(static_cast<int64_t>(s.is_type_record()), is_type_record));
|
||||
OZ (args.push_back(is_type_record));
|
||||
OZ (args.push_back(for_update));
|
||||
OZ (get_helper().create_call(ObString("spi_query"), get_spi_service().spi_query_, args, ret_err));
|
||||
} else { //有外部变量,走prepare/execute接口
|
||||
ObLLVMValue is_forall;
|
||||
OZ (get_helper().get_int8(static_cast<int64_t>(s.is_forall_sql()), is_forall));
|
||||
OZ (args.push_back(is_forall));
|
||||
OZ (get_helper().get_int8(static_cast<int64_t>(s.is_type_record()), is_type_record));
|
||||
OZ (args.push_back(is_type_record));
|
||||
OZ (args.push_back(for_update));
|
||||
OZ (get_helper().create_call(ObString("spi_execute"), get_spi_service().spi_execute_, args, ret_err));
|
||||
}
|
||||
@ -6425,6 +6546,9 @@ int ObPLCodeGenerator::generate_into(const ObPLInto &into,
|
||||
K(into.get_data_type()),
|
||||
K(into.get_not_null_flags()),
|
||||
K(into.get_pl_integer_ranges()));
|
||||
} else if (into.is_type_record() && 1 != into.get_into_data_type().count()) {
|
||||
ret = OB_ERR_EXPRESSION_WRONG_TYPE;
|
||||
LOG_WARN("coercion into multiple record targets not supported", K(ret));
|
||||
} else {
|
||||
ObLLVMType data_type;
|
||||
ObLLVMType data_type_pointer;
|
||||
@ -6562,7 +6686,7 @@ int ObPLCodeGenerator::generate_set_variable(int64_t expr,
|
||||
int ret = OB_SUCCESS;
|
||||
ObSEArray<ObLLVMValue, 5> args;
|
||||
ObLLVMValue expr_addr;
|
||||
ObLLVMValue is_default_value;
|
||||
ObLLVMValue is_default_value, need_copy;
|
||||
ObLLVMValue result;
|
||||
if (OB_FAIL(args.push_back(get_vars().at(CTX_IDX)))) { //PL的执行环境
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
@ -6576,6 +6700,10 @@ int ObPLCodeGenerator::generate_set_variable(int64_t expr,
|
||||
LOG_WARN("failed tio get int8", K(is_default), K(ret));
|
||||
} else if (OB_FAIL(args.push_back(is_default_value))) { //is_default
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(helper_.get_int8(false, need_copy))) {
|
||||
LOG_WARN("failed tio get int8", K(ret));
|
||||
} else if (OB_FAIL(args.push_back(need_copy))) {
|
||||
LOG_WARN("push_back error", K(ret));
|
||||
} else if (OB_FAIL(get_helper().create_call(ObString("spi_set_variable"), get_spi_service().spi_set_variable_, args, result))) {
|
||||
LOG_WARN("failed to create call", K(ret));
|
||||
} else if (OB_FAIL(check_success(result, stmt_id, in_notfound, in_warning))) {
|
||||
|
@ -268,7 +268,6 @@ public:
|
||||
const int64_t &cursor_index,
|
||||
const int64_t &limit,
|
||||
const ObUserDefinedType *user_defined_type,
|
||||
const ObIArray<ObDataType> &user_types,
|
||||
jit::ObLLVMValue &ret_err);
|
||||
int generate_close(const ObPLStmt &s,
|
||||
const uint64_t &package_id,
|
||||
@ -786,6 +785,7 @@ public:
|
||||
virtual int visit(const ObPLTrimStmt &s);
|
||||
virtual int visit(const ObPLInterfaceStmt &s);
|
||||
virtual int visit(const ObPLDoStmt &s);
|
||||
virtual int visit(const ObPLCaseStmt &s);
|
||||
|
||||
private:
|
||||
int find_next_procedence_condition(common::ObIArray<std::pair<ObPLConditionType, int64_t>> &conditions,
|
||||
|
@ -116,6 +116,7 @@
|
||||
INTERFACE_DEF(INTERFACE_DBMS_SESSION_CLEAR_IDENTIFIER, "CLEAR_IDENTIFIER", (ObDBMSSession::clear_identifier))
|
||||
INTERFACE_DEF(INTERFACE_DBMS_SESSION_SET_CONTEXT, "SET_CONTEXT", (ObDBMSSession::set_context))
|
||||
INTERFACE_DEF(INTERFACE_DBMS_SESSION_SET_IDENTIFIER, "SET_IDENTIFIER", (ObDBMSSession::set_identifier))
|
||||
INTERFACE_DEF(INTERFACE_DBMS_SESSION_RESET_PACKAGE, "RESET_PACKAGE", (ObDBMSSession::reset_package))
|
||||
// end of dbms_session
|
||||
|
||||
// start of dbms_udr
|
||||
|
@ -353,5 +353,27 @@ int ObPLPackageState::convert_changed_info_to_string_kvs(ObPLExecCtx &pl_ctx, Ob
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLPackageState::remove_user_variables_for_package_state(ObSQLSessionInfo &session)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t var_count = vars_.count();
|
||||
ObArenaAllocator allocator(ObModIds::OB_PL_TEMP);
|
||||
ObString key;
|
||||
for (int64_t var_idx = 0; var_idx < var_count; var_idx++) {
|
||||
// ignore error code, reset all variables
|
||||
key.reset();
|
||||
if (OB_FAIL(make_pkg_var_kv_key(allocator, var_idx, VARIABLE, key))) {
|
||||
LOG_WARN("make package var name failed", K(ret), K(package_id_), K(var_idx));
|
||||
} else if (session.user_variable_exists(key)) {
|
||||
if (OB_FAIL(session.remove_user_variable(key))) {
|
||||
LOG_WARN("fail to remove user var", K(ret), K(key), K(package_id_), K(var_idx));
|
||||
} else if (OB_FAIL(session.remove_changed_user_var(key))) {
|
||||
LOG_WARN("fail to remove change user var", K(ret), K(key), K(package_id_), K(var_idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // end namespace pl
|
||||
} // end namespace oceanbase
|
||||
|
@ -166,6 +166,8 @@ public:
|
||||
common::ObString &key,
|
||||
common::ObObj &value);
|
||||
inline bool get_serially_reusable() const { return serially_reusable_; }
|
||||
int remove_user_variables_for_package_state(ObSQLSessionInfo &session);
|
||||
uint64_t get_package_id() { return package_id_; }
|
||||
|
||||
ObIArray<ObObj> &get_vars() { return vars_; }
|
||||
|
||||
|
@ -342,7 +342,7 @@ int ObPLResolver::resolve(const ObStmtNodeTree *parse_tree, ObPLFunctionAST &fun
|
||||
}
|
||||
break;
|
||||
case T_SP_CASE: {
|
||||
RESOLVE_STMT(PL_IF, resolve_case, ObPLIfStmt);
|
||||
RESOLVE_STMT(PL_CASE, resolve_case, ObPLCaseStmt);
|
||||
}
|
||||
break;
|
||||
case T_SP_ITERATE: {
|
||||
@ -363,10 +363,14 @@ int ObPLResolver::resolve(const ObStmtNodeTree *parse_tree, ObPLFunctionAST &fun
|
||||
break;
|
||||
case T_SP_CURSOR_FOR_LOOP: {
|
||||
RESOLVE_STMT(PL_CURSOR_FOR_LOOP, resolve_cursor_for_loop, ObPLCursorForLoopStmt);
|
||||
if (!func.is_modifies_sql_data()) {
|
||||
func.set_reads_sql_data();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_SP_FORALL: {
|
||||
RESOLVE_STMT(PL_FORALL, resolve_forall, ObPLForAllStmt);
|
||||
func.set_modifies_sql_data();
|
||||
}
|
||||
break;
|
||||
case T_SP_REPEAT: {
|
||||
@ -396,10 +400,16 @@ int ObPLResolver::resolve(const ObStmtNodeTree *parse_tree, ObPLFunctionAST &fun
|
||||
break;
|
||||
case T_SP_EXECUTE_IMMEDIATE: {
|
||||
RESOLVE_STMT(PL_EXECUTE, resolve_execute_immediate, ObPLExecuteStmt);
|
||||
func.set_modifies_sql_data();
|
||||
}
|
||||
break;
|
||||
case T_SP_DO: {
|
||||
RESOLVE_STMT(PL_DO, resolve_do, ObPLDoStmt);
|
||||
RESOLVE_STMT(PL_DO, resolve_do, ObPLDoStmt);
|
||||
if (lib::is_mysql_mode()) {
|
||||
if (!func.is_reads_sql_data() && !func.is_modifies_sql_data()) {
|
||||
func.set_contains_sql();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_SP_EXTEND: {
|
||||
@ -440,14 +450,21 @@ int ObPLResolver::resolve(const ObStmtNodeTree *parse_tree, ObPLFunctionAST &fun
|
||||
break;
|
||||
case T_SP_RESIGNAL: {
|
||||
RESOLVE_STMT(PL_SIGNAL, resolve_resignal, ObPLSignalStmt);
|
||||
if (lib::is_mysql_mode() && !func.is_reads_sql_data() && !func.is_modifies_sql_data()) {
|
||||
func.set_contains_sql();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_SP_SIGNAL: {
|
||||
RESOLVE_STMT(PL_SIGNAL, resolve_signal, ObPLSignalStmt);
|
||||
if (lib::is_mysql_mode() && !func.is_reads_sql_data() && !func.is_modifies_sql_data()) {
|
||||
func.set_contains_sql();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case T_SP_CALL_STMT: {
|
||||
RESOLVE_STMT(PL_CALL, resolve_call, ObPLCallStmt);
|
||||
OX (func.set_external_state());
|
||||
}
|
||||
break;
|
||||
case T_SP_INNER_CALL_STMT: {
|
||||
@ -455,6 +472,7 @@ int ObPLResolver::resolve(const ObStmtNodeTree *parse_tree, ObPLFunctionAST &fun
|
||||
LOG_WARN("failed to resolve inner call", K(parse_tree), K(ret));
|
||||
} else {
|
||||
func.set_is_all_sql_stmt(false);
|
||||
func.set_external_state();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -463,6 +481,9 @@ int ObPLResolver::resolve(const ObStmtNodeTree *parse_tree, ObPLFunctionAST &fun
|
||||
LOG_WARN("fail to check decalre order", K(ret));
|
||||
} else {
|
||||
RESOLVE_STMT(PL_CURSOR, resolve_declare_cursor, ObPLDeclareCursorStmt);
|
||||
if (!func.is_modifies_sql_data()) {
|
||||
func.set_reads_sql_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -664,6 +685,9 @@ int ObPLResolver::resolve(const ObStmtNodeTree *parse_tree, ObPLFunctionAST &fun
|
||||
signal_stmt->set_str_len(STRLEN(ob_sqlstate(save_ret)));
|
||||
func.set_can_cached(false);
|
||||
func.set_is_all_sql_stmt(false);
|
||||
if (lib::is_mysql_mode() && !func.is_reads_sql_data() && !func.is_modifies_sql_data()) {
|
||||
func.set_contains_sql();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -976,6 +1000,10 @@ int ObPLResolver::resolve(const ObStmtNodeTree *parse_tree, ObPLPackageAST &pack
|
||||
case T_SP_DECL_CURSOR: {
|
||||
if (OB_FAIL(resolve_declare_cursor(parse_tree, package_ast))) {
|
||||
LOG_WARN("resovle package cursor declare failed", K(ret), K(parse_tree), K(package_ast));
|
||||
} else {
|
||||
if (!package_ast.is_modifies_sql_data()) {
|
||||
package_ast.set_reads_sql_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2923,6 +2951,7 @@ int ObPLResolver::resolve_assign(const ObStmtNodeTree *parse_tree, ObPLAssignStm
|
||||
OZ (current_block_->get_namespace().get_package_var(resolve_ctx_, package_id, var_idx, var));
|
||||
CK (OB_NOT_NULL(var));
|
||||
OX (expected_type = &(var->get_type()));
|
||||
OX (func.set_wps());
|
||||
} else if (T_OP_GET_SUBPROGRAM_VAR == into_expr->get_expr_type()) {
|
||||
CK (into_expr->get_param_count() >= 3);
|
||||
OX (subprogram_id = static_cast<const ObConstRawExpr *>(into_expr->get_param_expr(1))->get_value().get_uint64());
|
||||
@ -3043,9 +3072,11 @@ int ObPLResolver::resolve_if(const ObStmtNodeTree *parse_tree, ObPLIfStmt *stmt,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLResolver::resolve_case(const ObStmtNodeTree *parse_tree, ObPLIfStmt *stmt, ObPLFunctionAST &func)
|
||||
int ObPLResolver::resolve_case(const ObStmtNodeTree *parse_tree, ObPLCaseStmt *stmt, ObPLFunctionAST &func)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
ObConstRawExpr *case_var = nullptr;
|
||||
if (OB_ISNULL(parse_tree) || OB_ISNULL(stmt)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("parse_tree is NULL", K(parse_tree), K(stmt), K(ret));
|
||||
@ -3054,64 +3085,39 @@ int ObPLResolver::resolve_case(const ObStmtNodeTree *parse_tree, ObPLIfStmt *stm
|
||||
ObRawExpr *case_expr = NULL;
|
||||
const ObStmtNodeTree *expr_node = parse_tree->children_[0];
|
||||
set_item_type(T_SP_CASE);
|
||||
if (NULL == expr_node) {
|
||||
//没有case表达式
|
||||
} else if (OB_FAIL(resolve_expr(expr_node, func, case_expr,
|
||||
combine_line_and_col(expr_node->stmt_loc_), false))) {
|
||||
LOG_WARN("failed to resolve expr", K(expr_node), K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
|
||||
//解析when子句
|
||||
ObPLIfStmt *current_if = stmt;
|
||||
ObPLStmtBlock *current_block = current_block_;
|
||||
if (OB_SUCC(ret)) {
|
||||
const ObStmtNodeTree *when_list = parse_tree->children_[1];
|
||||
if (NULL == when_list) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("then node is NULL", K(when_list), K(parse_tree->children_), K(ret));
|
||||
} else if (T_WHEN_LIST != when_list->type_) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("Failed to resolve when", K(ret));
|
||||
} else if (0 >= when_list->num_child_) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected when list number", K(ret));
|
||||
} else {
|
||||
if (OB_FAIL(resolve_when(when_list->children_[0], case_expr, stmt, func))) {
|
||||
LOG_WARN("Failed to resolve when", K(ret));
|
||||
} else {
|
||||
int64_t idx = 1;
|
||||
while (OB_SUCC(ret) && idx < when_list->num_child_) {
|
||||
const ObStmtNodeTree *when_node = when_list->children_[idx];
|
||||
CK (OB_NOT_NULL(when_node));
|
||||
if (OB_SUCC(ret)) {
|
||||
ObPLStmtBlock *parent = NULL;
|
||||
parent = current_block_;
|
||||
if (OB_FAIL(make_block(func, parent, current_block_))) {
|
||||
LOG_WARN("failed to make block", K(ret));
|
||||
} else {
|
||||
ObPLStmt *stmt = NULL;
|
||||
current_if->set_else(current_block_);
|
||||
if (OB_FAIL(stmt_factory_.allocate(PL_IF, current_block_, stmt))) {
|
||||
LOG_WARN("failed to alloc stmt", K(ret));
|
||||
} else if (OB_ISNULL(current_if = static_cast<ObPLIfStmt*>(stmt))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("failed to static cast", K(ret));
|
||||
} else if (OB_FAIL(resolve_when(when_node, case_expr, current_if, func))) {
|
||||
LOG_WARN("Failed to resolve when", K(ret));
|
||||
} else if (OB_FAIL(current_block_->add_stmt(current_if))) {
|
||||
LOG_WARN("failed to add stmt", K(stmt), K(ret));
|
||||
} else {
|
||||
current_if->set_location(when_node->stmt_loc_.first_line_,
|
||||
when_node->stmt_loc_.first_column_);
|
||||
}
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(make_block(func, current_block, current_block_))) {
|
||||
LOG_WARN("failed to make block", K(ret));
|
||||
} else if (NULL == expr_node) {
|
||||
//没有case表达式
|
||||
} else if (OB_FAIL(resolve_expr(expr_node,
|
||||
func,
|
||||
case_expr,
|
||||
combine_line_and_col(expr_node->stmt_loc_)))) {
|
||||
LOG_WARN("failed to resolve expr", K(expr_node), K(ret));
|
||||
} else if (OB_FAIL(current_block_->get_namespace().add_symbol(
|
||||
ObString(""), // anonymous variable for holding case expr value
|
||||
case_expr->get_data_type()))) {
|
||||
LOG_WARN("failed to add CASE expr var to symbol table");
|
||||
} else {
|
||||
stmt->set_case_expr(func.get_expr_count() - 1);
|
||||
stmt->set_case_var(func.get_symbol_table().get_count() - 1);
|
||||
OZ(expr_factory_.create_raw_expr(T_QUESTIONMARK, case_var));
|
||||
CK(OB_NOT_NULL(case_var));
|
||||
if (OB_SUCC(ret)) {
|
||||
ObObjParam val;
|
||||
val.set_unknown(stmt->get_case_var());
|
||||
val.set_param_meta();
|
||||
case_var->set_value(val);
|
||||
case_var->set_result_type(case_expr->get_result_type());
|
||||
OZ (case_var->extract_info());
|
||||
}
|
||||
}
|
||||
|
||||
//解析when子句
|
||||
const ObStmtNodeTree *when_list = parse_tree->children_[1];
|
||||
OZ (resolve_when(when_list, case_var, stmt, func));
|
||||
|
||||
//解析else子句
|
||||
if (OB_SUCC(ret)) {
|
||||
const ObStmtNodeTree *else_node = parse_tree->children_[2];
|
||||
@ -3161,7 +3167,7 @@ int ObPLResolver::resolve_case(const ObStmtNodeTree *parse_tree, ObPLIfStmt *stm
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
current_if->set_else(else_block);
|
||||
stmt->set_else_clause(else_block);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3173,56 +3179,53 @@ int ObPLResolver::resolve_case(const ObStmtNodeTree *parse_tree, ObPLIfStmt *stm
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLResolver::resolve_when(const ObStmtNodeTree *parse_tree, const ObRawExpr *case_expr, ObPLIfStmt *stmt, ObPLFunctionAST &func)
|
||||
int ObPLResolver::resolve_when(const ObStmtNodeTree *parse_tree, ObRawExpr *case_expr_var, ObPLCaseStmt *stmt, ObPLFunctionAST &func)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(parse_tree) || OB_ISNULL(stmt)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("parse_tree is NULL", K(parse_tree), K(stmt), K(ret));
|
||||
} else if (T_SP_WHEN != parse_tree->type_) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("parse_tree of when list is NULL", K(parse_tree), K(stmt), K(ret));
|
||||
} else if (T_WHEN_LIST != parse_tree->type_) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("Invalid when node type", K(parse_tree->type_), K(ret));
|
||||
} else if (0 >= parse_tree->num_child_) { // one when clause at least
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected when list number", K(ret));
|
||||
} else {
|
||||
//解析expr then结构
|
||||
ObRawExpr *expr = NULL;
|
||||
ObPLStmtBlock *then_block = NULL;
|
||||
ObPLDataType data_type(ObTinyIntType);
|
||||
bool is_bool_stmt = false;
|
||||
if (OB_ISNULL(case_expr) && lib::is_mysql_mode()) {
|
||||
is_bool_stmt = true;
|
||||
}
|
||||
set_item_type(T_SP_WHEN);
|
||||
if (OB_FAIL(resolve_then(parse_tree,
|
||||
func,
|
||||
OB_ISNULL(case_expr) ? &data_type : NULL,
|
||||
expr,
|
||||
then_block,
|
||||
is_bool_stmt))) {
|
||||
LOG_WARN("failed to resolve then", K(ret));
|
||||
} else {
|
||||
stmt->set_then(then_block);
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (NULL == case_expr) {
|
||||
if (OB_FAIL(func.add_expr(expr))) {
|
||||
LOG_WARN("failed to add expr", K(*expr), K(ret));
|
||||
} else {
|
||||
stmt->set_cond(func.get_expr_count() - 1);
|
||||
}
|
||||
} else {
|
||||
ObRawExpr *cond_expr = NULL;
|
||||
if (OB_FAIL(ObRawExprUtils::create_equal_expr(expr_factory_, &resolve_ctx_.session_info_, case_expr, expr, cond_expr))) {
|
||||
LOG_WARN("failed to create_equal_expr", K(ret));
|
||||
} else {
|
||||
if (OB_FAIL(func.add_expr(cond_expr))) {
|
||||
LOG_WARN("failed to add expr", K(*cond_expr), K(ret));
|
||||
} else {
|
||||
OZ (cond_expr->formalize(&resolve_ctx_.session_info_));
|
||||
OX (stmt->set_cond(func.get_expr_count() - 1));
|
||||
}
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < parse_tree->num_child_; ++i) {
|
||||
ObRawExpr *expr = nullptr;
|
||||
ObPLStmtBlock *body = nullptr;
|
||||
ObPLDataType data_type(ObTinyIntType);
|
||||
bool is_bool_stmt = false;
|
||||
if (!case_expr_var && lib::is_mysql_mode()) {
|
||||
is_bool_stmt = true;
|
||||
}
|
||||
set_item_type(T_SP_WHEN);
|
||||
if (OB_FAIL(make_block(func, current_block_, body))) {
|
||||
LOG_WARN("failed to make block");
|
||||
} else if (OB_FAIL(resolve_then(parse_tree->children_[i],
|
||||
func,
|
||||
case_expr_var ? nullptr : &data_type,
|
||||
expr,
|
||||
body,
|
||||
is_bool_stmt))) {
|
||||
LOG_WARN("failed to resolve then", K(ret));
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && case_expr_var) {
|
||||
ObRawExpr *cmp_expr = nullptr;
|
||||
|
||||
OZ (ObRawExprUtils::create_equal_expr(expr_factory_,
|
||||
&resolve_ctx_.session_info_,
|
||||
case_expr_var,
|
||||
expr,
|
||||
cmp_expr));
|
||||
OX (expr = cmp_expr);
|
||||
}
|
||||
|
||||
OZ (func.add_expr(expr));
|
||||
OZ (expr->formalize(&resolve_ctx_.session_info_));
|
||||
OZ (stmt->add_when_clause(func.get_expr_count() - 1, body));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@ -3556,20 +3559,9 @@ int ObPLResolver::resolve_cursor_for_loop(
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("user type is null", K(ret));
|
||||
} else {
|
||||
// cursor nested complex type, report not support
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < user_type->get_member_count(); ++i) {
|
||||
if (!user_type->get_member(i)->is_obj_type()) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_WARN("cursor nested complex type", K(ret));
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "cursor nested complex type");
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
stmt->set_user_type(user_type);
|
||||
stmt->set_index_index(func.get_symbol_table().get_count() - 1);
|
||||
if (OB_FAIL(body_block->get_namespace().expand_data_type(user_type, stmt->get_expand_user_types()))) {
|
||||
LOG_WARN("fail to expand data type", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4599,6 +4591,17 @@ int ObPLResolver::resolve_static_sql(const ObStmtNodeTree *parse_tree, ObPLSql &
|
||||
K(ret), K(prepare_result.type_), K(func.get_compile_flag()));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (stmt::T_SELECT == prepare_result.type_) {
|
||||
if (!func.is_modifies_sql_data()) {
|
||||
func.set_reads_sql_data();
|
||||
}
|
||||
} else if (ObStmt::is_dml_write_stmt(prepare_result.type_)) {
|
||||
func.set_modifies_sql_data();
|
||||
} else if (!func.is_reads_sql_data() && !func.is_modifies_sql_data()) {
|
||||
func.set_contains_sql();
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObArray<int64_t> idxs;
|
||||
@ -4640,6 +4643,9 @@ int ObPLResolver::resolve_static_sql(const ObStmtNodeTree *parse_tree, ObPLSql &
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (prepare_result.is_bulk_) {
|
||||
static_into.set_bulk();
|
||||
}
|
||||
if (OB_FAIL(static_into.set_into(idxs, current_block_->get_namespace(), prepare_result.into_exprs_))) {
|
||||
LOG_WARN("failed to set into exprs", K(prepare_result.into_exprs_), K(idxs), K(ret));
|
||||
}
|
||||
@ -4662,9 +4668,9 @@ int ObPLResolver::resolve_static_sql(const ObStmtNodeTree *parse_tree, ObPLSql &
|
||||
ObPLDataType type;
|
||||
OZ (access_expr->get_final_type(type));
|
||||
OZ (static_into.check_into(
|
||||
func, current_block_->get_namespace(), type.is_collection_type()));
|
||||
func, current_block_->get_namespace(), prepare_result.is_bulk_));
|
||||
} else {
|
||||
OZ (static_into.check_into(func, current_block_->get_namespace(), false));
|
||||
OZ (static_into.check_into(func, current_block_->get_namespace(), prepare_result.is_bulk_));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4816,6 +4822,33 @@ int ObPLResolver::resolve_execute_immediate(
|
||||
const ObStmtNodeTree *using_node = parse_tree->children_[2];
|
||||
if (NULL != using_node) {
|
||||
OZ (resolve_using(using_node, stmt->get_using(), func));
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (stmt->has_out() && (parse_tree->children_[3] || parse_tree->children_[1])) {
|
||||
ret = OB_ERR_INOUT_PARAM_PLACEMENT_NOT_PROPERLY;
|
||||
LOG_WARN("PLS-00254: OUT and IN/OUT modes cannot be used in this context Cause: \
|
||||
actual parameter mode (OUT, or IN/OUT) is not used properly in USING clause.\
|
||||
For USING clause in an OPEN statement, only IN mode is allowed.", K(ret));
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_using().count(); ++i) {
|
||||
const ObRawExpr *expr = func.get_expr(stmt->get_using_index(i));
|
||||
if (OB_ISNULL(expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("expr is NULL", K(ret));
|
||||
} else if (expr->is_obj_access_expr()) {
|
||||
pl::ObPLDataType final_type;
|
||||
const ObObjAccessRawExpr *access_expr = static_cast<const ObObjAccessRawExpr *>(expr);
|
||||
OZ(access_expr->get_final_type(final_type));
|
||||
if (OB_SUCC(ret) && final_type.is_type_record() && stmt->is_out(i)) {
|
||||
ret =OB_ERR_EXPRESSION_WRONG_TYPE;
|
||||
LOG_WARN("expr is wrong type", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && stmt->is_out(i)) {
|
||||
OZ (stmt->generate_into_variable_info(current_block_->get_namespace(), *expr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6325,6 +6358,13 @@ int ObPLResolver::resolve_cursor_def(const ObString &cursor_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (prepare_result.for_update_) {
|
||||
func.set_modifies_sql_data();
|
||||
} else if (!func.is_modifies_sql_data()) {
|
||||
func.set_reads_sql_data();
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(func.add_dependency_objects(prepare_result.ref_objects_))) {
|
||||
LOG_WARN("failed to set ref object", K(prepare_result.ref_objects_), K(ret));
|
||||
@ -6726,10 +6766,14 @@ int ObPLResolver::resolve_open(
|
||||
ObPLCursor *cursor = NULL;
|
||||
cursor = current_block_->get_namespace().get_cursor_table()->get_cursor(index);
|
||||
if (OB_SUCC(ret) && OB_NOT_NULL(cursor)) {
|
||||
if (cursor->is_for_update()) {
|
||||
func.set_modifies_sql_data();
|
||||
}
|
||||
if (PL_REF_CURSOR_TYPE == cursor->get_cursor_type().get_type()) {
|
||||
if (cursor->get_package_id() != current_block_->get_namespace().get_package_id()
|
||||
|| cursor->get_routine_id() != current_block_->get_namespace().get_routine_id()) {
|
||||
func.set_open_external_ref_cursor();
|
||||
func.set_external_state();
|
||||
}
|
||||
} else {
|
||||
if (!var->get_pl_data_type().is_ref_cursor_type()
|
||||
@ -6926,6 +6970,7 @@ int ObPLResolver::resolve_open_for(
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "non-string type dynamic sql");
|
||||
} else {
|
||||
stmt->set_dynamic_sql(func.get_expr_count() - 1);
|
||||
func.set_modifies_sql_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6964,6 +7009,13 @@ int ObPLResolver::resolve_fetch(
|
||||
CK (OB_NOT_NULL(
|
||||
cursor = current_block_->get_namespace().get_cursor_table()->get_cursor(index)));
|
||||
OX (stmt->set_index(cursor->get_package_id(), cursor->get_routine_id(), cursor->get_index()));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (cursor->is_for_update()) {
|
||||
func.set_modifies_sql_data();
|
||||
} else if (!func.is_modifies_sql_data()) {
|
||||
func.set_reads_sql_data();
|
||||
}
|
||||
}
|
||||
|
||||
//解析into
|
||||
if (OB_SUCC(ret)) {
|
||||
@ -6990,130 +7042,94 @@ int ObPLResolver::resolve_fetch(
|
||||
bool is_compatible = true;
|
||||
const ObRecordType *return_type = static_cast<const ObRecordType*>(cursor_type);
|
||||
stmt->set_user_type(cursor_type);
|
||||
if (OB_FAIL(current_block_->get_namespace().expand_data_type(cursor_type, stmt->get_expand_user_types()))) {
|
||||
LOG_WARN("fail to expand data type", K(ret));
|
||||
} else if (return_type->get_record_member_count() != stmt->get_data_type().count()
|
||||
if (return_type->get_record_member_count() != stmt->get_data_type().count()
|
||||
&& return_type->get_record_member_count() != stmt->get_into().count()) {
|
||||
ret = OB_ERR_WRONG_FETCH_INTO_NUM;
|
||||
LOG_WARN("wrong number of values in the INTO list of a FETCH statement", K(ret));
|
||||
} else {
|
||||
// cursor nested complex type, report not support
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_into().count(); ++i) {
|
||||
const ObRawExpr *raw_expr = NULL;
|
||||
CK (OB_NOT_NULL(raw_expr = func.get_expr(stmt->get_into(i))));
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (raw_expr->get_result_type().is_ext()) {
|
||||
int64_t udt_id = raw_expr->get_result_type().get_accuracy().accuracy_;
|
||||
if (T_OBJ_ACCESS_REF == raw_expr->get_expr_type() && OB_INVALID_ID == udt_id) {
|
||||
//objaccess expr udt id is invalid if final type is basic data type.
|
||||
const ObObjAccessRawExpr *obj_access_expr = static_cast<const ObObjAccessRawExpr *>(raw_expr);
|
||||
ObExprResType result_type;
|
||||
pl::ObPLDataType final_type;
|
||||
if (OB_FAIL(obj_access_expr->get_final_type(final_type))) {
|
||||
LOG_WARN("failed to get final type", K(ret));
|
||||
} else if (!final_type.is_obj_type()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("fetch into var type is unexpected", K(ret));
|
||||
}
|
||||
} else {
|
||||
const ObUserDefinedType *into_var_type = NULL;
|
||||
OZ (current_block_->get_namespace().get_user_type(udt_id, into_var_type));
|
||||
CK (OB_NOT_NULL(into_var_type));
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (into_var_type->is_record_type()) {
|
||||
for (int64_t j = 0; OB_SUCC(ret) && j < into_var_type->get_member_count(); ++j) {
|
||||
if (!into_var_type->get_member(j)->is_obj_type()) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_WARN("cursor nested complex type", K(ret));
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "cursor nested complex type");
|
||||
}
|
||||
}
|
||||
} else if (into_var_type->is_collection_type()) {
|
||||
const ObCollectionType *coll_type = static_cast<const ObCollectionType*>(into_var_type);
|
||||
CK (OB_NOT_NULL(coll_type));
|
||||
if (coll_type->get_element_type().is_obj_type()) {
|
||||
// do nothing
|
||||
} else if (coll_type->get_element_type().is_record_type()) {
|
||||
const ObUserDefinedType *element_type = NULL;
|
||||
OZ (current_block_->get_namespace().get_user_type(coll_type->get_element_type().get_user_type_id(), element_type));
|
||||
CK (OB_NOT_NULL(element_type));
|
||||
for (int64_t j = 0; OB_SUCC(ret) && j < element_type->get_member_count(); ++j) {
|
||||
if (!element_type->get_member(j)->is_obj_type()) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_WARN("cursor nested complex type", K(ret));
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "cursor nested complex type");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_WARN("cursor nested complex type", K(ret));
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "cursor nested complex type");
|
||||
}
|
||||
}
|
||||
}
|
||||
//如果into后面只有一个变量且为record类型,
|
||||
bool has_type_record_type = false;
|
||||
const ObPLDataType *into_var_type = NULL;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && !has_type_record_type && i < stmt->get_into_data_type().count(); ++i) {
|
||||
into_var_type = &stmt->get_into_data_type(i);
|
||||
//type定义的record
|
||||
if (into_var_type->is_type_record()) {
|
||||
has_type_record_type = true;
|
||||
}
|
||||
}
|
||||
bool has_record_type = false;
|
||||
for (int64_t i = 0;
|
||||
OB_SUCC(ret) && is_compatible && i < return_type->get_record_member_count();
|
||||
++i) {
|
||||
const ObPLDataType *left = return_type->get_record_member_type(i);
|
||||
ObDataType right;
|
||||
CK (OB_NOT_NULL(left));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (!left->is_obj_type()) {
|
||||
has_record_type = true;
|
||||
}
|
||||
if (!has_record_type) {
|
||||
right = stmt->get_data_type(i);
|
||||
if (OB_SUCC(ret) && has_type_record_type && stmt->get_into_data_type().count() != 1) {
|
||||
//后续新增494的错误码
|
||||
ret = OB_ERR_MULTI_RECORD;
|
||||
LOG_WARN("coercion into multiple record targets not supported", K(ret));
|
||||
}
|
||||
/* 走到这里如果没报错,有两种可能:
|
||||
1.into变量只有唯一一个type record.
|
||||
2.into变量无type record */
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
const ObUserDefinedType *into_user_type = NULL;
|
||||
const ObRecordType *into_record_type = NULL;
|
||||
int64_t into_data_type_count = 0;
|
||||
if (has_type_record_type) {
|
||||
CK (1 == stmt->get_into_data_type().count());
|
||||
OZ (current_block_->get_namespace().get_user_type(stmt->get_into_data_type(0).get_user_type_id(), into_user_type));
|
||||
CK (OB_NOT_NULL(into_user_type));
|
||||
CK (into_user_type->is_record_type());
|
||||
OX (into_record_type = static_cast<const ObRecordType*>(into_user_type));
|
||||
OX (into_data_type_count = into_record_type->get_record_member_count());
|
||||
} else {
|
||||
into_data_type_count = stmt->get_into_data_type().count();
|
||||
}
|
||||
// 依次比较cursor member和所有into变量
|
||||
const ObPLDataType *left = NULL;
|
||||
const ObPLDataType *right = NULL;
|
||||
CK (return_type->get_record_member_count() == into_data_type_count);
|
||||
for (int64_t i = 0; OB_SUCC(ret) && is_compatible && i < into_data_type_count; ++i) {
|
||||
left = return_type->get_record_member_type(i);
|
||||
if (has_type_record_type) {
|
||||
right = into_record_type->get_record_member_type(i);
|
||||
} else {
|
||||
const ObRawExpr *raw_expr = NULL;
|
||||
if (return_type->get_record_member_count() != stmt->get_into().count()) {
|
||||
ret = OB_ERR_TYPE_MISMATCH_IN_FETCH;
|
||||
LOG_WARN("type not compatible",
|
||||
K(return_type->get_record_member_count()),
|
||||
K(stmt->get_into().count()),
|
||||
K(ret));
|
||||
right = &stmt->get_into_data_type(i);
|
||||
}
|
||||
CK (OB_NOT_NULL(left));
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (left->is_obj_type() &&
|
||||
right->is_obj_type() &&
|
||||
NULL != right->get_data_type() &&
|
||||
!right->get_data_type()->get_meta_type().is_ext()) {
|
||||
if (right->get_data_type()->get_meta_type().is_null() &&
|
||||
stmt->get_into().count() > i &&
|
||||
is_question_mark_value(func.get_expr(stmt->get_into(i)))) {
|
||||
OZ (set_question_mark_type(func.get_expr(stmt->get_into(i)), left));
|
||||
} else {
|
||||
CK (OB_NOT_NULL(raw_expr = func.get_expr(stmt->get_into(i))));
|
||||
OV (raw_expr->get_result_type().is_ext(), OB_ERR_UNEXPECTED, KPC(raw_expr));
|
||||
OX (right.set_meta_type(raw_expr->get_result_type()));
|
||||
OX (right.set_accuracy(raw_expr->get_result_type().get_accuracy()));
|
||||
CK (OB_NOT_NULL(left->get_data_type()));
|
||||
OX (is_compatible = cast_supported(left->get_data_type()->get_obj_type(),
|
||||
left->get_data_type()->get_collation_type(),
|
||||
right->get_data_type()->get_obj_type(),
|
||||
right->get_data_type()->get_collation_type()));
|
||||
}
|
||||
} else if ((!left->is_obj_type() ||
|
||||
(left->get_data_type() != NULL && left->get_data_type()->get_meta_type().is_ext()))
|
||||
&&
|
||||
(!right->is_obj_type() ||
|
||||
(right->get_data_type() != NULL && right->get_data_type()->get_meta_type().is_ext()))) {
|
||||
uint64_t left_udt_id = (NULL == left->get_data_type()) ? left->get_user_type_id()
|
||||
: left->get_data_type()->get_udt_id();
|
||||
uint64_t right_udt_id = (NULL == right->get_data_type()) ? right->get_user_type_id()
|
||||
: right->get_data_type()->get_udt_id();
|
||||
if (left_udt_id != right_udt_id) {
|
||||
is_compatible = false;
|
||||
} else {
|
||||
// same composite type, compatible is true, do nothing.
|
||||
}
|
||||
} else {
|
||||
is_compatible = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (left->is_obj_type() && !right.get_meta_type().is_ext()) {
|
||||
if (right.get_meta_type().is_null()
|
||||
&& stmt->get_into().count() > i
|
||||
&& is_question_mark_value(func.get_expr(stmt->get_into(i)))) {
|
||||
OZ (set_question_mark_type(func.get_expr(stmt->get_into(i)), left));
|
||||
} else {
|
||||
CK (OB_NOT_NULL(left->get_data_type()));
|
||||
OX (is_compatible = cast_supported(left->get_data_type()->get_obj_type(),
|
||||
left->get_data_type()->get_collation_type(),
|
||||
right.get_obj_type(),
|
||||
right.get_collation_type()));
|
||||
}
|
||||
} else if ((!left->is_obj_type()
|
||||
|| (left->get_data_type() != NULL
|
||||
&& left->get_data_type()->get_meta_type().is_ext()))
|
||||
&& right.get_meta_type().is_ext()) {
|
||||
uint64_t left_udt_id =
|
||||
(NULL == left->get_data_type())
|
||||
? left->get_user_type_id() : left->get_data_type()->get_udt_id();
|
||||
if (left_udt_id != right.get_udt_id()) {
|
||||
// left and right both composite.
|
||||
OZ (check_composite_compatible(current_block_->get_namespace(),
|
||||
left->get_user_type_id(),
|
||||
right.get_udt_id(),
|
||||
is_compatible), KPC(left), K(right));
|
||||
} else {
|
||||
// same composite type, compatible is true, do nothing.
|
||||
}
|
||||
} else {
|
||||
is_compatible = false;
|
||||
if (OB_SUCC(ret) && !is_compatible) {
|
||||
ret = OB_ERR_TYPE_MISMATCH_IN_FETCH;
|
||||
LOG_WARN("type not compatible", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7179,6 +7195,13 @@ int ObPLResolver::resolve_close(
|
||||
cursor = current_block_->get_namespace().get_cursor_table()->get_cursor(index)));
|
||||
OX (stmt->set_index(
|
||||
cursor->get_package_id(), cursor->get_routine_id(), cursor->get_index()));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (cursor->is_for_update()) {
|
||||
func.set_modifies_sql_data();
|
||||
} else if (!func.is_modifies_sql_data()) {
|
||||
func.set_reads_sql_data();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -8228,6 +8251,28 @@ int ObPLResolver::set_cm_warn_on_fail(ObRawExpr *&expr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLResolver::analyze_expr_type(ObRawExpr *&expr,
|
||||
ObPLCompileUnitAST &unit_ast)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
CK (OB_NOT_NULL(expr));
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (T_OP_GET_PACKAGE_VAR == expr->get_expr_type()) {
|
||||
OX (unit_ast.set_rps());
|
||||
} else if (T_FUN_UDF == expr->get_expr_type()) {
|
||||
OX (unit_ast.set_external_state());
|
||||
} else {
|
||||
for (int64_t i = 0;
|
||||
OB_SUCC(ret) &&
|
||||
(!unit_ast.is_rps() || !unit_ast.is_external_state()) &&
|
||||
i < expr->get_param_count();
|
||||
++i) {
|
||||
OZ (analyze_expr_type(expr->get_param_expr(i), unit_ast));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLResolver::resolve_expr(const ParseNode *node,
|
||||
ObPLCompileUnitAST &unit_ast,
|
||||
ObRawExpr *&expr,
|
||||
@ -8243,7 +8288,7 @@ int ObPLResolver::resolve_expr(const ParseNode *node,
|
||||
CK (OB_NOT_NULL(expr));
|
||||
bool is_order = false;
|
||||
OZ (replace_object_compare_expr(expr, unit_ast, is_order));
|
||||
|
||||
OZ (analyze_expr_type(expr, unit_ast));
|
||||
// check op illegal
|
||||
if (OB_SUCC(ret) && !OB_ISNULL(expr)
|
||||
&& (T_OP_EQ == expr->get_expr_type() || T_OP_NE == expr->get_expr_type())) {
|
||||
@ -8561,6 +8606,10 @@ int ObPLResolver::transform_subquery_expr(const ParseNode *node,
|
||||
LOG_WARN("failed to set precalc exprs", K(prepare_result.exec_params_), K(ret));
|
||||
} else if (OB_FAIL(func.add_dependency_objects(prepare_result.ref_objects_))) {
|
||||
LOG_WARN("failed to add dependency objects", K(prepare_result.ref_objects_), K(ret));
|
||||
} else {
|
||||
if (!func.is_modifies_sql_data()) {
|
||||
func.set_reads_sql_data();
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
@ -10016,6 +10065,7 @@ int ObPLResolver::resolve_udf_info(
|
||||
|
||||
CK (OB_NOT_NULL(udf_info.ref_expr_));
|
||||
CK (OB_NOT_NULL(current_block_));
|
||||
OX (func.set_external_state());
|
||||
OZ (schema_checker.init(resolve_ctx_.schema_guard_));
|
||||
OZ (ObRawExprUtils::rebuild_expr_params(udf_info, &expr_factory_, expr_params), K(udf_info), K(access_idxs));
|
||||
{
|
||||
@ -10269,6 +10319,23 @@ int ObPLResolver::resolve_udf_info(
|
||||
OX (udf_raw_expr->set_is_udt_cons(udf_info.is_udf_udt_cons()));
|
||||
OX (udf_raw_expr->set_is_udt_udf(routine_info->is_udt_routine()));
|
||||
OX (udf_raw_expr->set_is_deterministic(routine_info->is_deterministic()));
|
||||
if (OB_SUCC(ret)) {
|
||||
bool enable_parallel = true;
|
||||
if (udf_raw_expr->is_parallel_enable()) {
|
||||
//do nothing
|
||||
} else {
|
||||
if (routine_info->is_modifies_sql_data() ||
|
||||
routine_info->is_wps() ||
|
||||
routine_info->is_rps() ||
|
||||
routine_info->is_has_sequence() ||
|
||||
routine_info->is_external_state()) {
|
||||
enable_parallel = false;
|
||||
} else if (routine_info->is_reads_sql_data()) {
|
||||
enable_parallel = true;
|
||||
}
|
||||
OX (udf_raw_expr->set_parallel_enable(enable_parallel));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)
|
||||
&& udf_info.is_udf_udt_cons()
|
||||
&& OB_NOT_NULL(udf_raw_expr->get_param_expr(0))) {
|
||||
@ -11109,6 +11176,18 @@ int ObPLResolver::resolve_var(ObQualifiedName &q_name, ObPLBlockNS &ns,
|
||||
&resolve_ctx_.schema_guard_, ns, expr, for_write))) {
|
||||
LOG_WARN("failed to make var from access", K(ret), K(q_name), K(access_idxs));
|
||||
} else { /*do nothing*/ }
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (ObObjAccessIdx::is_package_variable(access_idxs)) {
|
||||
if (for_write) {
|
||||
OX (func.set_wps());
|
||||
} else {
|
||||
OX (func.set_rps());
|
||||
}
|
||||
} else if (ObObjAccessIdx::is_get_variable(access_idxs)) {
|
||||
OX (func.set_external_state());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -12238,11 +12317,17 @@ int ObPLResolver::resolve_into(const ParseNode *into_node, ObPLInto &into, ObPLF
|
||||
static_cast<int>(into_list->children_[i]->str_len_),
|
||||
into_list->children_[i]->str_value_);
|
||||
}
|
||||
if (OB_SUCC(ret) && 1 == into_node->value_) {
|
||||
into.set_bulk();
|
||||
}
|
||||
CK (OB_NOT_NULL(expr));
|
||||
OZ (func.add_expr(expr));
|
||||
OZ (into.add_into(func.get_expr_count() - 1, current_block_->get_namespace(), *expr));
|
||||
if (OB_SUCC(ret) && expr->is_obj_access_expr()) {
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (expr->is_obj_access_expr()) {
|
||||
OZ (func.add_obj_access_expr(expr));
|
||||
} else if (T_OP_GET_PACKAGE_VAR == expr->get_expr_type()) {
|
||||
OX (func.set_wps());
|
||||
}
|
||||
}
|
||||
|
||||
@ -12395,6 +12480,7 @@ int ObPLResolver::resolve_condition(const ObStmtNodeTree *parse_tree,
|
||||
obj_version.object_type_ = DEPENDENCY_PACKAGE;
|
||||
obj_version.version_ = package_info->get_schema_version();
|
||||
OZ (func.add_dependency_object(obj_version));
|
||||
OX (func.set_rps());
|
||||
}
|
||||
OX (*value = &(condition->get_value()));
|
||||
}
|
||||
@ -12710,6 +12796,9 @@ int ObPLResolver::resolve_sequence_object(const ObQualifiedName &q_name,
|
||||
OX (obj_version.version_ = schema_version);
|
||||
OZ (unit_ast.add_dependency_object(obj_version));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
unit_ast.set_has_sequence();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ret = OB_ERR_SP_UNDECLARED_VAR;
|
||||
@ -12996,6 +13085,7 @@ int ObPLResolver::resolve_cursor(ObPLCompileUnitAST &func,
|
||||
obj_version.object_type_ = DEPENDENCY_PACKAGE;
|
||||
obj_version.version_ = package_info->get_schema_version();
|
||||
OZ (func.add_dependency_object(obj_version));
|
||||
OX (func.set_rps());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -13622,9 +13712,15 @@ int ObPLResolver::resolve_routine_decl_param_list(const ParseNode *param_list,
|
||||
break;
|
||||
case MODE_OUT:
|
||||
param_mode = PL_PARAM_OUT;
|
||||
if (!unit_ast.is_package()) {
|
||||
unit_ast.set_has_out_param();
|
||||
}
|
||||
break;
|
||||
case MODE_INOUT:
|
||||
param_mode = PL_PARAM_INOUT;
|
||||
if (!unit_ast.is_package()) {
|
||||
unit_ast.set_has_out_param();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
@ -14203,6 +14299,39 @@ int ObPLResolver::resolve_routine_def(const ObStmtNodeTree *parse_tree,
|
||||
OZ (routine_table.set_routine_ast(idx, routine_ast));
|
||||
OX (unit_ast.add_dependency_objects(routine_ast->get_dependency_table()));
|
||||
OX (unit_ast.set_can_cached(routine_ast->get_can_cached()));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (unit_ast.is_modifies_sql_data()) {
|
||||
// do nothing
|
||||
} else if (routine_ast->is_modifies_sql_data()) {
|
||||
unit_ast.set_modifies_sql_data();
|
||||
} else if (unit_ast.is_reads_sql_data()) {
|
||||
// do nothing
|
||||
} else if (routine_ast->is_reads_sql_data()) {
|
||||
unit_ast.set_reads_sql_data();
|
||||
} else if (unit_ast.is_contains_sql()) {
|
||||
// do nothing
|
||||
} else if (routine_ast->is_contains_sql()) {
|
||||
unit_ast.set_contains_sql();
|
||||
} else if (routine_ast->is_no_sql()) {
|
||||
unit_ast.set_no_sql();
|
||||
}
|
||||
if (routine_ast->is_wps()) {
|
||||
unit_ast.set_wps();
|
||||
}
|
||||
if (routine_ast->is_rps()) {
|
||||
unit_ast.set_rps();
|
||||
}
|
||||
if (routine_ast->is_has_sequence()) {
|
||||
unit_ast.set_has_sequence();
|
||||
}
|
||||
/*if (routine_ast->is_has_out_param()) {
|
||||
unit_ast.set_has_out_param();
|
||||
}*/
|
||||
if (routine_ast->is_external_state()) {
|
||||
unit_ast.set_external_state();
|
||||
}
|
||||
}
|
||||
OX (routine_info->set_analyze_flag(routine_ast->get_analyze_flag()));
|
||||
// 将routine param中的外部类型加入到当前namespace的type table中。
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < routine_info->get_param_count(); ++i) {
|
||||
ObPLRoutineParam *param = routine_info->get_params().at(i);
|
||||
|
@ -566,7 +566,7 @@ private:
|
||||
bool is_for_param_type = false);
|
||||
int resolve_assign(const ObStmtNodeTree *parse_tree, ObPLAssignStmt *stmt, ObPLFunctionAST &func);
|
||||
int resolve_if(const ObStmtNodeTree *parse_tree, ObPLIfStmt *stmt, ObPLFunctionAST &func);
|
||||
int resolve_case(const ObStmtNodeTree *parse_tree, ObPLIfStmt *stmt, ObPLFunctionAST &func);
|
||||
int resolve_case(const ObStmtNodeTree *parse_tree, ObPLCaseStmt *stmt, ObPLFunctionAST &func);
|
||||
int resolve_iterate(const ObStmtNodeTree *parse_tree, ObPLIterateStmt *stmt, ObPLFunctionAST &func);
|
||||
int resolve_leave(const ObStmtNodeTree *parse_tree, ObPLLeaveStmt *stmt, ObPLFunctionAST &func);
|
||||
int resolve_while(const ObStmtNodeTree *parse_tree, ObPLWhileStmt *stmt, ObPLFunctionAST &func);
|
||||
@ -641,6 +641,8 @@ private:
|
||||
const ObPLDataType *expected_type = NULL);
|
||||
int get_actually_pl_type(const ObPLDataType *&type);
|
||||
int set_cm_warn_on_fail(ObRawExpr *&expr);
|
||||
int analyze_expr_type(ObRawExpr *&expr,
|
||||
ObPLCompileUnitAST &unit_ast);
|
||||
int resolve_expr(const ParseNode *node, ObPLCompileUnitAST &unit_ast,
|
||||
sql::ObRawExpr *&expr, uint64_t line_number = 0, /* where this expr called */
|
||||
bool need_add = true, const ObPLDataType *expected_type = NULL,
|
||||
@ -683,7 +685,7 @@ private:
|
||||
int resolve_package_stmt_list(const ObStmtNodeTree *node, ObPLStmtBlock *&block, ObPLPackageAST &package);
|
||||
int resolve_stmt_list(const ObStmtNodeTree *parse_tree, ObPLStmtBlock *&stmt, ObPLFunctionAST &func,
|
||||
bool stop_search_label = false, bool in_handler_scope = false);
|
||||
int resolve_when(const ObStmtNodeTree *parse_tree, const ObRawExpr *case_expr, ObPLIfStmt *stmt, ObPLFunctionAST &func);
|
||||
int resolve_when(const ObStmtNodeTree *parse_tree, ObRawExpr *case_expr_var, ObPLCaseStmt *stmt, ObPLFunctionAST &func);
|
||||
int resolve_then(const ObStmtNodeTree *parse_tree,
|
||||
ObPLFunctionAST &func,
|
||||
ObPLDataType *data_type,
|
||||
|
@ -105,7 +105,7 @@ int ObPLRouter::check_error_in_resolve(int code)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLRouter::analyze(ObString &route_sql, ObIArray<ObDependencyInfo> &dep_info)
|
||||
int ObPLRouter::analyze(ObString &route_sql, ObIArray<ObDependencyInfo> &dep_info, ObRoutineInfo &routine_info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
HEAP_VAR(ObPLFunctionAST, func_ast, inner_allocator_) {
|
||||
@ -128,6 +128,32 @@ int ObPLRouter::analyze(ObString &route_sql, ObIArray<ObDependencyInfo> &dep_inf
|
||||
routine_info_.get_object_type(),
|
||||
0, dep_attr, dep_attr));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (func_ast.is_modifies_sql_data()) {
|
||||
routine_info.set_modifies_sql_data();
|
||||
} else if (func_ast.is_reads_sql_data()) {
|
||||
routine_info.set_reads_sql_data();
|
||||
} else if (func_ast.is_contains_sql()) {
|
||||
routine_info.set_contains_sql();
|
||||
} else if (func_ast.is_no_sql()) {
|
||||
routine_info.set_no_sql();
|
||||
}
|
||||
if (func_ast.is_wps()) {
|
||||
routine_info.set_wps();
|
||||
}
|
||||
if (func_ast.is_rps()) {
|
||||
routine_info.set_rps();
|
||||
}
|
||||
if (func_ast.is_has_sequence()) {
|
||||
routine_info.set_has_sequence();
|
||||
}
|
||||
if (func_ast.is_has_out_param()) {
|
||||
routine_info.set_has_out_param();
|
||||
}
|
||||
if (func_ast.is_external_state()) {
|
||||
routine_info.set_external_state();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
expr_factory_(inner_allocator_) {}
|
||||
virtual ~ObPLRouter() {}
|
||||
|
||||
int analyze(ObString &route_sql, common::ObIArray<share::schema::ObDependencyInfo> &dep_infos);
|
||||
int analyze(ObString &route_sql, common::ObIArray<share::schema::ObDependencyInfo> &dep_infos, ObRoutineInfo &routine_info);
|
||||
int simple_resolve(ObPLFunctionAST &func_ast);
|
||||
static int analyze_stmt(const ObPLStmt *stmt, ObString &route_sql);
|
||||
|
||||
|
@ -3136,6 +3136,43 @@ int ObPLBlockNS::get_cursor_by_name(const ObExprResolveContext &ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLBlockNS::expand_data_type_once(const ObUserDefinedType *user_type,
|
||||
ObIArray<ObDataType> &types,
|
||||
ObIArray<bool> *not_null_flags,
|
||||
ObIArray<int64_t> *pls_ranges) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
CK (OB_NOT_NULL(user_type));
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < user_type->get_member_count(); ++i) {
|
||||
const ObPLDataType *member = user_type->get_member(i);
|
||||
CK (OB_NOT_NULL(member));
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (member->is_obj_type()) {
|
||||
CK (OB_NOT_NULL(member->get_data_type()));
|
||||
OZ (types.push_back(*member->get_data_type()), i);
|
||||
if (OB_NOT_NULL(not_null_flags)) {
|
||||
OZ (not_null_flags->push_back(member->get_not_null()));
|
||||
}
|
||||
if (OB_NOT_NULL(pls_ranges)) {
|
||||
ObPLIntegerRange range;
|
||||
OZ (pls_ranges->push_back(member->is_pl_integer_type() ? member->get_range() : range.range_));
|
||||
}
|
||||
} else {
|
||||
ObDataType ext_type;
|
||||
ext_type.set_obj_type(ObExtendType);
|
||||
OZ (types.push_back(ext_type), i);
|
||||
if (OB_NOT_NULL(not_null_flags)) {
|
||||
OZ (not_null_flags->push_back(false));
|
||||
}
|
||||
if (OB_NOT_NULL(pls_ranges)) {
|
||||
ObPLIntegerRange range;
|
||||
OZ (pls_ranges->push_back(range.range_));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLBlockNS::expand_data_type(const ObUserDefinedType *user_type,
|
||||
ObIArray<ObDataType> &types,
|
||||
ObIArray<bool> *not_null_flags,
|
||||
@ -3389,82 +3426,122 @@ int64_t ObPLBlockNS::to_string(char* buf, const int64_t buf_len) const
|
||||
return pos;
|
||||
}
|
||||
|
||||
int ObPLInto::generate_into_variable_info(ObPLBlockNS &ns, const ObRawExpr &expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
pl::ObPLDataType final_type;
|
||||
pl::ObPLDataType pl_data_type;
|
||||
// T_OBJ_ACCESS_REF expr, access obj type (not user defined type)
|
||||
bool access_obj_type = false;
|
||||
if (expr.is_obj_access_expr()) {
|
||||
// case:
|
||||
// type num_table is table of number;
|
||||
// ...
|
||||
// num_table nums;
|
||||
// ...
|
||||
// fetch c_cursor into nums(1);
|
||||
//
|
||||
// We got `num(1)` by T_OBJ_ACCESS_REF expression for write. T_OBJ_ACCESS_REF return
|
||||
// the address of ObObj by extend value in execution, so %expr's result type is set to
|
||||
// ObExtendType. We get the obj type from final type of T_OBJ_ACCESS_REF here.
|
||||
const auto &access_expr = static_cast<const ObObjAccessRawExpr &>(expr);
|
||||
OZ(access_expr.get_final_type(final_type));
|
||||
OX(access_obj_type = !final_type.is_user_type());
|
||||
if (bulk_ && !access_obj_type && final_type.is_collection_type()) {
|
||||
const pl::ObUserDefinedType *user_type = NULL;
|
||||
OZ (ns.get_pl_data_type_by_id(final_type.get_user_type_id(), user_type));
|
||||
CK (OB_NOT_NULL(user_type));
|
||||
if (OB_SUCC(ret)) {
|
||||
const ObCollectionType *coll_type = static_cast<const ObCollectionType*>(user_type);
|
||||
CK (OB_NOT_NULL(coll_type));
|
||||
OX (final_type = coll_type->get_element_type());
|
||||
OX(access_obj_type = !final_type.is_user_type());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (expr.get_result_type().is_ext() && !access_obj_type) {
|
||||
const pl::ObUserDefinedType *user_type = NULL;
|
||||
if (expr.is_obj_access_expr()) {
|
||||
// do nothing, %final_type already fetched
|
||||
} else if (T_QUESTIONMARK == expr.get_expr_type()) {
|
||||
CK (OB_NOT_NULL(ns.get_symbol_table()));
|
||||
int64_t var_index = static_cast<const ObConstRawExpr&>(expr).get_value().get_int();
|
||||
const ObPLVar *var = ns.get_symbol_table()->get_symbol(var_index);
|
||||
CK (OB_NOT_NULL(var));
|
||||
OX (final_type = var->get_pl_data_type());
|
||||
} else {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("Invalid expr type used in INTO clause", K(expr), K(ret));
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (final_type.is_cursor_type() || final_type.is_opaque_type()) {
|
||||
ObDataType ext_type;
|
||||
ext_type.set_obj_type(ObExtendType);
|
||||
OZ (data_type_.push_back(ext_type));
|
||||
OZ (not_null_flags_.push_back(false));
|
||||
ObPLIntegerRange range;
|
||||
OZ (pl_integer_ranges_.push_back(range.range_));
|
||||
OX (pl_data_type.set_data_type(ext_type));
|
||||
OX (pl_data_type.set_type(PL_OBJ_TYPE));
|
||||
OZ (into_data_type_.push_back(pl_data_type));
|
||||
} else {
|
||||
if (final_type.is_type_record()) {
|
||||
ObArray<ObDataType> basic_types;
|
||||
ObArray<bool> not_null_flags;
|
||||
ObArray<int64_t> pls_ranges;
|
||||
is_type_record_ = true;
|
||||
OZ (ns.get_pl_data_type_by_id(final_type.get_user_type_id(), user_type));
|
||||
CK (OB_NOT_NULL(user_type));
|
||||
// 只能展一层
|
||||
OZ (ns.expand_data_type_once(user_type, basic_types, ¬_null_flags, &pls_ranges));
|
||||
OZ (append(data_type_, basic_types));
|
||||
OZ (append(not_null_flags_, not_null_flags));
|
||||
OZ (append(pl_integer_ranges_, pls_ranges));
|
||||
} else {
|
||||
ObDataType ext_type;
|
||||
ObDataType type;
|
||||
ObPLIntegerRange range;
|
||||
ext_type.set_obj_type(ObExtendType);
|
||||
OZ (data_type_.push_back(ext_type));
|
||||
OZ (not_null_flags_.push_back(false));
|
||||
OZ (pl_integer_ranges_.push_back(range.range_));
|
||||
}
|
||||
OZ (into_data_type_.push_back(final_type));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ObDataType type;
|
||||
ObPLIntegerRange range;
|
||||
bool flag = false;
|
||||
if (access_obj_type) {
|
||||
type.set_meta_type(final_type.get_data_type()->get_meta_type());
|
||||
type.set_accuracy(final_type.get_data_type()->get_accuracy());
|
||||
} else {
|
||||
type.set_meta_type(expr.get_result_type().get_obj_meta());
|
||||
type.set_accuracy(expr.get_result_type().get_accuracy());
|
||||
}
|
||||
OZ (calc_type_constraint(expr, ns, flag, range), expr);
|
||||
OZ (data_type_.push_back(type), type);
|
||||
OZ (not_null_flags_.push_back(flag), type, flag);
|
||||
OZ (pl_integer_ranges_.push_back(range.range_));
|
||||
OX (pl_data_type.set_data_type(type));
|
||||
OX (pl_data_type.set_type(PL_OBJ_TYPE));
|
||||
OZ (into_data_type_.push_back(pl_data_type));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPLInto::add_into(int64_t idx, ObPLBlockNS &ns, const ObRawExpr &expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(into_.push_back(idx))) {
|
||||
LOG_WARN("Failed to add into", K(idx), K(ret));
|
||||
} else {
|
||||
pl::ObPLDataType final_type;
|
||||
// T_OBJ_ACCESS_REF expr, access obj type (not user defined type)
|
||||
bool access_obj_type = false;
|
||||
if (expr.is_obj_access_expr()) {
|
||||
// case:
|
||||
// type num_table is table of number;
|
||||
// ...
|
||||
// num_table nums;
|
||||
// ...
|
||||
// fetch c_cursor into nums(1);
|
||||
//
|
||||
// We got `num(1)` by T_OBJ_ACCESS_REF expression for write. T_OBJ_ACCESS_REF return
|
||||
// the address of ObObj by extend value in execution, so %expr's result type is set to
|
||||
// ObExtendType. We get the obj type from final type of T_OBJ_ACCESS_REF here.
|
||||
const auto &access_expr = static_cast<const ObObjAccessRawExpr &>(expr);
|
||||
OZ(access_expr.get_final_type(final_type));
|
||||
OX(access_obj_type = !final_type.is_user_type());
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (expr.get_result_type().is_ext() && !access_obj_type) {
|
||||
const pl::ObUserDefinedType *user_type = NULL;
|
||||
if (expr.is_obj_access_expr()) {
|
||||
// do nothing, %final_type already fetched
|
||||
} else if (T_QUESTIONMARK == expr.get_expr_type()) {
|
||||
CK (OB_NOT_NULL(ns.get_symbol_table()));
|
||||
int64_t var_index = static_cast<const ObConstRawExpr&>(expr).get_value().get_int();
|
||||
const ObPLVar *var = ns.get_symbol_table()->get_symbol(var_index);
|
||||
CK (OB_NOT_NULL(var));
|
||||
OX (final_type = var->get_pl_data_type());
|
||||
} else {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("Invalid expr type used in INTO clause", K(idx), K(expr), K(ret));
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (final_type.is_cursor_type() || final_type.is_opaque_type()) {
|
||||
ObDataType ext_type;
|
||||
ext_type.set_obj_type(ObExtendType);
|
||||
OZ (data_type_.push_back(ext_type));
|
||||
OZ (not_null_flags_.push_back(false));
|
||||
ObPLIntegerRange range;
|
||||
OZ (pl_integer_ranges_.push_back(range.range_));
|
||||
} else {
|
||||
ObArray<ObDataType> basic_types;
|
||||
ObArray<bool> not_null_flags;
|
||||
ObArray<int64_t> pls_ranges;
|
||||
OZ (ns.get_pl_data_type_by_id(final_type.get_user_type_id(), user_type));
|
||||
CK (OB_NOT_NULL(user_type));
|
||||
OZ (ns.expand_data_type(user_type, basic_types, ¬_null_flags, &pls_ranges));
|
||||
OZ (append(data_type_, basic_types));
|
||||
OZ (append(not_null_flags_, not_null_flags));
|
||||
OZ (append(pl_integer_ranges_, pls_ranges));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ObDataType type;
|
||||
ObPLIntegerRange range;
|
||||
bool flag = false;
|
||||
if (access_obj_type) {
|
||||
type.set_meta_type(final_type.get_data_type()->get_meta_type());
|
||||
type.set_accuracy(final_type.get_data_type()->get_accuracy());
|
||||
} else {
|
||||
type.set_meta_type(expr.get_result_type().get_obj_meta());
|
||||
type.set_accuracy(expr.get_result_type().get_accuracy());
|
||||
}
|
||||
OZ (calc_type_constraint(expr, ns, flag, range), expr);
|
||||
OZ (data_type_.push_back(type), type);
|
||||
OZ (not_null_flags_.push_back(flag), type, flag);
|
||||
OZ (pl_integer_ranges_.push_back(range.range_));
|
||||
}
|
||||
OZ (generate_into_variable_info(ns, expr));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -3596,9 +3673,7 @@ int ObPLInto::check_into(ObPLFunctionAST &func, ObPLBlockNS &ns, bool is_bulk)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && is_bulk) {
|
||||
set_bulk();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -4358,6 +4433,13 @@ int ObPLStmtFactory::allocate(ObPLStmtType type, const ObPLStmtBlock *block, ObP
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PL_CASE: {
|
||||
stmt = static_cast<ObPLStmt *>(allocator_.alloc(sizeof(ObPLCaseStmt)));
|
||||
if (NULL != stmt) {
|
||||
stmt = new(stmt)ObPLCaseStmt(allocator_);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:{
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("Unexpected stmt type", K(ret), K(type));
|
||||
@ -4521,6 +4603,10 @@ int ObPLDoStmt::accept(ObPLStmtVisitor &visitor) const
|
||||
{
|
||||
return visitor.visit(*this);
|
||||
}
|
||||
int ObPLCaseStmt::accept(ObPLStmtVisitor &visitor) const
|
||||
{
|
||||
return visitor.visit(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -834,10 +834,7 @@ public:
|
||||
accessors_(allocator),
|
||||
priv_user_(),
|
||||
loc_(0),
|
||||
is_no_sql_(false),
|
||||
is_reads_sql_data_(false),
|
||||
is_modifies_sql_data_(false),
|
||||
is_contains_sql_(true){}
|
||||
analyze_flag_(0) {}
|
||||
virtual ~ObPLRoutineInfo();
|
||||
|
||||
int make_routine_param(common::ObIAllocator &allocator,
|
||||
@ -942,6 +939,20 @@ public:
|
||||
|
||||
virtual bool is_invoker_right() const { return compile_flag_.compile_with_invoker_right(); }
|
||||
|
||||
inline void set_analyze_flag(uint64_t flag) { analyze_flag_ = flag; }
|
||||
inline uint64_t get_analyze_flag() const { return analyze_flag_; }
|
||||
|
||||
virtual void set_wps() { is_wps_ = true; }
|
||||
virtual bool is_wps() const { return is_wps_; }
|
||||
virtual void set_rps() { is_rps_ = true; }
|
||||
virtual bool is_rps() const { return is_rps_; }
|
||||
virtual void set_has_sequence() { is_has_sequence_ = true; }
|
||||
virtual bool is_has_sequence() const { return is_has_sequence_; }
|
||||
virtual void set_has_out_param() { is_has_out_param_ = true; }
|
||||
virtual bool is_has_out_param() const { return is_has_out_param_; }
|
||||
virtual void set_external_state() { is_external_state_ = true; }
|
||||
virtual bool is_external_state() const { return is_external_state_; }
|
||||
|
||||
virtual void set_result_cache() { is_result_cache_ = true; }
|
||||
virtual bool is_result_cache() const { return is_result_cache_; }
|
||||
|
||||
@ -983,7 +994,8 @@ public:
|
||||
K_(is_parallel_enable),
|
||||
K_(is_udt_routine),
|
||||
K_(accessors),
|
||||
K_(loc));
|
||||
K_(loc),
|
||||
K_(analyze_flag));
|
||||
private:
|
||||
common::ObIAllocator &allocator_;
|
||||
uint64_t tenant_id_;
|
||||
@ -1011,10 +1023,21 @@ private:
|
||||
ObPLSEArray<AccessorItem> accessors_;
|
||||
common::ObString priv_user_;
|
||||
uint64_t loc_;
|
||||
bool is_no_sql_;
|
||||
bool is_reads_sql_data_;
|
||||
bool is_modifies_sql_data_;
|
||||
bool is_contains_sql_;
|
||||
union {
|
||||
uint64_t analyze_flag_;
|
||||
struct {
|
||||
uint64_t is_no_sql_ : 1;
|
||||
uint64_t is_reads_sql_data_ : 1;
|
||||
uint64_t is_modifies_sql_data_ : 1;
|
||||
uint64_t is_contains_sql_ : 1;
|
||||
uint64_t is_wps_ : 1;
|
||||
uint64_t is_rps_ : 1;
|
||||
uint64_t is_has_sequence_ : 1;
|
||||
uint64_t is_has_out_param_ : 1;
|
||||
uint64_t is_external_state_ : 1;
|
||||
uint64_t reserved_:54;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
class ObPLFunctionAST;
|
||||
@ -1411,6 +1434,10 @@ public:
|
||||
ObIArray<ObDataType> &types,
|
||||
ObIArray<bool> *not_null_flags = NULL,
|
||||
ObIArray<int64_t> *pls_ranges = NULL) const;
|
||||
int expand_data_type_once(const ObUserDefinedType *user_type,
|
||||
ObIArray<ObDataType> &types,
|
||||
ObIArray<bool> *not_null_flags = NULL,
|
||||
ObIArray<int64_t> *pls_ranges = NULL) const;
|
||||
inline bool is_procedure(ObProcType routine_type) const
|
||||
{
|
||||
return STANDALONE_PROCEDURE == routine_type
|
||||
@ -1503,7 +1530,8 @@ public:
|
||||
dependency_table_(),
|
||||
compile_flag_(),
|
||||
can_cached_(true),
|
||||
priv_user_()
|
||||
priv_user_(),
|
||||
analyze_flag_(0)
|
||||
{}
|
||||
|
||||
virtual ~ObPLCompileUnitAST() {}
|
||||
@ -1586,6 +1614,28 @@ public:
|
||||
virtual int64_t get_version() const = 0;
|
||||
virtual uint64_t get_database_id() const = 0;
|
||||
|
||||
virtual uint64_t get_analyze_flag() const { return analyze_flag_; }
|
||||
|
||||
virtual void set_no_sql() { is_no_sql_ = true; is_reads_sql_data_ = false; is_modifies_sql_data_ = false; is_contains_sql_ = false; }
|
||||
virtual bool is_no_sql() const { return is_no_sql_; }
|
||||
virtual void set_reads_sql_data() { is_no_sql_ = false; is_reads_sql_data_ = true; is_modifies_sql_data_ = false; is_contains_sql_ = false; }
|
||||
virtual bool is_reads_sql_data() const { return is_reads_sql_data_; }
|
||||
virtual void set_modifies_sql_data() { is_no_sql_ = false; is_reads_sql_data_ = false; is_modifies_sql_data_ = true; is_contains_sql_ = false; }
|
||||
virtual bool is_modifies_sql_data() const { return is_modifies_sql_data_; }
|
||||
virtual void set_contains_sql() { is_no_sql_ = false; is_reads_sql_data_ = false; is_modifies_sql_data_ = false; is_contains_sql_ = true; }
|
||||
virtual bool is_contains_sql() const { return is_contains_sql_; }
|
||||
|
||||
virtual void set_wps() { is_wps_ = true; }
|
||||
virtual bool is_wps() const { return is_wps_; }
|
||||
virtual void set_rps() { is_rps_ = true; }
|
||||
virtual bool is_rps() const { return is_rps_; }
|
||||
virtual void set_has_sequence() { is_has_sequence_ = true; }
|
||||
virtual bool is_has_sequence() const { return is_has_sequence_; }
|
||||
virtual void set_has_out_param() { is_has_out_param_ = true; }
|
||||
virtual bool is_has_out_param() const { return is_has_out_param_; }
|
||||
virtual void set_external_state() { is_external_state_ = true; }
|
||||
virtual bool is_external_state() const { return is_external_state_; }
|
||||
|
||||
ObPLSymbolDebugInfoTable &get_symbol_debuginfo_table()
|
||||
{
|
||||
return symbol_debuginfo_table_;
|
||||
@ -1618,6 +1668,21 @@ protected:
|
||||
ObPLCompileFlag compile_flag_;
|
||||
bool can_cached_;
|
||||
ObString priv_user_;
|
||||
union {
|
||||
uint64_t analyze_flag_;
|
||||
struct {
|
||||
uint64_t is_no_sql_ : 1;
|
||||
uint64_t is_reads_sql_data_ : 1;
|
||||
uint64_t is_modifies_sql_data_ : 1;
|
||||
uint64_t is_contains_sql_ : 1;
|
||||
uint64_t is_wps_ : 1;
|
||||
uint64_t is_rps_ : 1;
|
||||
uint64_t is_has_sequence_ : 1;
|
||||
uint64_t is_has_out_param_ : 1;
|
||||
uint64_t is_external_state_ : 1;
|
||||
uint64_t reserved_:54;
|
||||
};
|
||||
};
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObPLCompileUnitAST);
|
||||
};
|
||||
@ -1723,6 +1788,7 @@ enum ObPLStmtType
|
||||
PL_TRIM,
|
||||
PL_INTERFACE,
|
||||
PL_DO,
|
||||
PL_CASE,
|
||||
MAX_PL_STMT
|
||||
};
|
||||
|
||||
@ -1974,6 +2040,56 @@ private:
|
||||
ObPLStmtBlock *else_;
|
||||
};
|
||||
|
||||
class ObPLCaseStmt : public ObPLStmt {
|
||||
public:
|
||||
ObPLCaseStmt(common::ObIAllocator &allocator)
|
||||
: ObPLStmt(PL_CASE),
|
||||
case_expr_idx_(OB_INVALID_INDEX), case_var_idx_(OB_INVALID_INDEX),
|
||||
when_(allocator), else_(nullptr) {}
|
||||
virtual ~ObPLCaseStmt() {}
|
||||
|
||||
virtual int64_t get_child_size() const override { return when_.count() + 1; }
|
||||
virtual const ObPLStmt *get_child_stmt(int64_t i) const override {
|
||||
ObPLStmt *ret = nullptr;
|
||||
int64_t when_count = when_.count();
|
||||
if (OB_LIKELY(0 <= i && i <= when_count)) {
|
||||
if (OB_LIKELY(i < when_count)) {
|
||||
ret = when_[i].body_;
|
||||
} else {
|
||||
ret = else_;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
virtual int accept(ObPLStmtVisitor &visitor) const override;
|
||||
|
||||
struct WhenClause {
|
||||
int64_t expr_;
|
||||
ObPLStmtBlock *body_;
|
||||
|
||||
TO_STRING_KV(K_(expr), K_(body));
|
||||
};
|
||||
using WhenClauses = ObPLSEArray<WhenClause>;
|
||||
|
||||
void set_case_expr(int64_t case_expr_idx) { case_expr_idx_ = case_expr_idx; }
|
||||
int64_t get_case_expr() const { return case_expr_idx_; }
|
||||
void set_case_var(int64_t case_var_idx) { case_var_idx_ = case_var_idx; }
|
||||
int64_t get_case_var() const { return case_var_idx_; }
|
||||
int add_when_clause(int64_t expr, ObPLStmtBlock *body) {
|
||||
return when_.push_back(WhenClause{expr, body});
|
||||
}
|
||||
const WhenClauses &get_when_clauses() const { return when_; }
|
||||
void set_else_clause(ObPLStmtBlock *stmts) { else_ = stmts; }
|
||||
const ObPLStmtBlock *get_else_clause() const { return else_; }
|
||||
|
||||
private:
|
||||
int64_t case_expr_idx_;
|
||||
int64_t case_var_idx_;
|
||||
WhenClauses when_;
|
||||
ObPLStmtBlock *else_;
|
||||
};
|
||||
|
||||
typedef common::ObSEArray<ObObjAccessIdx, 4> ObObjAccessIndexs;
|
||||
typedef common::ObSEArray<ObObjAccessIndexs, 4> ObObjAccessArray;
|
||||
|
||||
@ -1985,7 +2101,9 @@ public:
|
||||
not_null_flags_(allocator),
|
||||
pl_integer_ranges_(allocator),
|
||||
data_type_(allocator),
|
||||
bulk_(false) {}
|
||||
into_data_type_(allocator),
|
||||
bulk_(false),
|
||||
is_type_record_(false) {}
|
||||
virtual ~ObPLInto() {}
|
||||
|
||||
inline const common::ObIArray<int64_t> &get_into() const { return into_; }
|
||||
@ -1995,11 +2113,16 @@ public:
|
||||
int set_into(const common::ObIArray<int64_t> &idxs, ObPLBlockNS &ns, const common::ObIArray<sql::ObRawExpr*> &exprs);
|
||||
inline int add_into(int64_t idx) { return into_.push_back(idx); }
|
||||
int add_into(int64_t idx, ObPLBlockNS &ns, const sql::ObRawExpr &expr);
|
||||
int generate_into_variable_info(ObPLBlockNS &ns, const ObRawExpr &expr);
|
||||
inline const common::ObIArray<ObDataType> &get_data_type() const { return data_type_; }
|
||||
inline common::ObIArray<ObDataType> &get_data_type() { return data_type_; }
|
||||
inline const ObDataType &get_data_type(int64_t i) const { return data_type_.at(i); }
|
||||
inline int set_data_type(const common::ObIArray<ObDataType> &types) { return append(data_type_, types); }
|
||||
inline int add_data_type(ObDataType &type) { return data_type_.push_back(type); }
|
||||
inline const common::ObIArray<ObPLDataType> &get_into_data_type() const { return into_data_type_; }
|
||||
inline common::ObIArray<ObPLDataType> &get_into_data_type() { return into_data_type_; }
|
||||
inline const ObPLDataType &get_into_data_type(int64_t i) const { return into_data_type_.at(i); }
|
||||
inline bool is_type_record() const { return is_type_record_; }
|
||||
inline bool is_bulk() const { return bulk_; }
|
||||
inline void set_bulk() { bulk_ = true; }
|
||||
int check_into(ObPLFunctionAST &func, ObPLBlockNS &ns, bool is_bulk);
|
||||
@ -2022,7 +2145,9 @@ protected:
|
||||
ObPLSEArray<bool> not_null_flags_;
|
||||
ObPLSEArray<int64_t> pl_integer_ranges_;
|
||||
ObPLSEArray<ObDataType> data_type_;
|
||||
ObPLSEArray<ObPLDataType> into_data_type_;
|
||||
bool bulk_;
|
||||
bool is_type_record_; // 表示into后面是否只有一个type定义的record类型(非object定义)
|
||||
};
|
||||
|
||||
class ObPLLoopControl : public ObPLStmt
|
||||
@ -2218,8 +2343,7 @@ public:
|
||||
cursor_idx_(OB_INVALID_INDEX),
|
||||
params_(allocator),
|
||||
need_declare_(false),
|
||||
user_type_(NULL),
|
||||
expand_user_types_() {}
|
||||
user_type_(NULL) {}
|
||||
|
||||
virtual ~ObPLCursorForLoopStmt() {}
|
||||
|
||||
@ -2288,8 +2412,6 @@ public:
|
||||
user_type_ = user_type;
|
||||
}
|
||||
|
||||
ObIArray<ObDataType> &get_expand_user_types() { return expand_user_types_; }
|
||||
const ObIArray<ObDataType> &get_expand_user_types() const { return expand_user_types_; }
|
||||
inline void set_need_declare(bool need) { need_declare_ = need; }
|
||||
inline bool get_need_declare() const { return need_declare_; }
|
||||
|
||||
@ -2303,7 +2425,6 @@ private:
|
||||
ObPLSEArray<int64_t> params_; //cursor的实参
|
||||
bool need_declare_; // 是否是SQL语句, 需要在codegen时声明
|
||||
const ObUserDefinedType *user_type_; // CURSOR返回值类型
|
||||
ObSEArray<ObDataType, 8> expand_user_types_; //expand return type
|
||||
};
|
||||
|
||||
class ObPLSqlStmt;
|
||||
@ -2939,8 +3060,7 @@ public:
|
||||
routine_id_(OB_INVALID_ID),
|
||||
idx_(common::OB_INVALID_INDEX),
|
||||
limit_(INT64_MAX),
|
||||
user_type_(NULL),
|
||||
expand_user_types_() {}
|
||||
user_type_(NULL) {}
|
||||
virtual ~ObPLFetchStmt() {}
|
||||
|
||||
int accept(ObPLStmtVisitor &visitor) const;
|
||||
@ -2963,8 +3083,6 @@ public:
|
||||
{
|
||||
user_type_ = user_type;
|
||||
}
|
||||
ObIArray<ObDataType> &get_expand_user_types() { return expand_user_types_; }
|
||||
const ObIArray<ObDataType> &get_expand_user_types() const { return expand_user_types_; }
|
||||
inline int64_t get_limit() const { return limit_; }
|
||||
inline void set_limit(int64_t limit) { limit_ = limit; }
|
||||
|
||||
@ -2976,7 +3094,6 @@ private:
|
||||
int64_t idx_; //symbol表里的下标
|
||||
int64_t limit_; //INT64_MAX:是bulk fetch但是没有limit子句
|
||||
const ObUserDefinedType *user_type_; // CURSOR返回值类型
|
||||
ObSEArray<ObDataType, 8> expand_user_types_; //expand return type
|
||||
};
|
||||
|
||||
class ObPLCloseStmt : public ObPLStmt
|
||||
@ -3210,6 +3327,7 @@ public:
|
||||
virtual int visit(const ObPLTrimStmt &s) = 0;
|
||||
virtual int visit(const ObPLInterfaceStmt &s) = 0;
|
||||
virtual int visit(const ObPLDoStmt &s) = 0;
|
||||
virtual int visit(const ObPLCaseStmt &s) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -404,6 +404,10 @@ public:
|
||||
inline bool is_object_type() const {
|
||||
return (is_record_type() || is_opaque_type()) && is_udt_type();
|
||||
}
|
||||
//存储过程内部通过type定义的record
|
||||
inline bool is_type_record() const {
|
||||
return is_record_type() && !is_udt_type();
|
||||
}
|
||||
inline bool is_lob_type() const {
|
||||
return PL_OBJ_TYPE == type_ && obj_type_.get_meta_type().is_lob_locator();
|
||||
}
|
||||
@ -739,6 +743,7 @@ enum ObPLCursorFlag {
|
||||
SESSION_CURSOR = 2, // this cursor is alloc in session memory
|
||||
TRANSFERING_RESOURCE = 4, // this cursor is returned by a udf
|
||||
SYNC_CURSOR = 8, // this cursor from package cursor sync, can not used by this server.
|
||||
INVALID_CURSOR = 16, // this cursor is convert to a dbms cursor, invalid for dynamic cursor op.
|
||||
};
|
||||
class ObPLCursorInfo
|
||||
{
|
||||
@ -954,6 +959,9 @@ public:
|
||||
inline void set_sync_cursor() { set_flag_bit(SYNC_CURSOR); }
|
||||
inline bool is_sync_cursor() { return test_flag_bit(SYNC_CURSOR); }
|
||||
|
||||
inline void set_invalid_cursor() { set_flag_bit(INVALID_CURSOR); }
|
||||
inline bool is_invalid_cursor() { return test_flag_bit(INVALID_CURSOR); }
|
||||
|
||||
static int prepare_entity(sql::ObSQLSessionInfo &session,
|
||||
lib::MemoryContext &entity);
|
||||
int prepare_spi_result(ObPLExecCtx *ctx, sql::ObSPIResultSet *&spi_result);
|
||||
|
@ -734,6 +734,18 @@ int ObRecordType::is_compatble(const ObRecordType &other, bool &is_comp) const
|
||||
left->get_data_type()->get_collation_type(),
|
||||
right->get_data_type()->get_obj_type(),
|
||||
right->get_data_type()->get_collation_type()));
|
||||
} else if ((!left->is_obj_type() ||
|
||||
(left->get_data_type() != NULL && left->get_data_type()->get_meta_type().is_ext()))
|
||||
&&
|
||||
(!right->is_obj_type() ||
|
||||
(right->get_data_type() != NULL && right->get_data_type()->get_meta_type().is_ext()))) {
|
||||
uint64_t left_udt_id = (NULL == left->get_data_type()) ? left->get_user_type_id()
|
||||
: left->get_data_type()->get_udt_id();
|
||||
uint64_t right_udt_id = (NULL == right->get_data_type()) ? right->get_user_type_id()
|
||||
: right->get_data_type()->get_udt_id();
|
||||
if (left_udt_id != right_udt_id) {
|
||||
is_comp = false;
|
||||
}
|
||||
} else {
|
||||
is_comp = false;
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ bool ObPLObjectKey::is_equal(const ObILibCacheKey &other) const
|
||||
int ObPLObjectValue::init(const ObILibCacheObject &cache_obj, ObPLCacheCtx &pc_ctx)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const pl::ObPLCompileUnit &pl_object = static_cast<const pl::ObPLCompileUnit &>(cache_obj);
|
||||
const pl::ObPLCacheObject &pl_object = static_cast<const pl::ObPLCacheObject &>(cache_obj);
|
||||
if (OB_FAIL(add_match_info(pc_ctx, &pc_ctx.key_, cache_obj))) {
|
||||
LOG_WARN("failed to add_match_info", K(ret));
|
||||
} else {
|
||||
@ -497,8 +497,12 @@ int ObPLObjectValue::add_match_info(ObILibCacheCtx &ctx,
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
ObPLCacheCtx& pc_ctx = static_cast<ObPLCacheCtx&>(ctx);
|
||||
const pl::ObPLCompileUnit &cache_object = static_cast<const pl::ObPLCompileUnit &>(cache_obj);
|
||||
if (OB_UNLIKELY(!cache_object.is_prcr() && !cache_object.is_sfc() && !cache_object.is_pkg() && !cache_object.is_anon())) {
|
||||
const pl::ObPLCacheObject &cache_object = static_cast<const pl::ObPLCacheObject &>(cache_obj);
|
||||
if (OB_UNLIKELY(!cache_object.is_prcr() &&
|
||||
!cache_object.is_sfc() &&
|
||||
!cache_object.is_pkg() &&
|
||||
!cache_object.is_anon() &&
|
||||
!cache_object.is_call_stmt())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("cache object is invalid", K(cache_object));
|
||||
} else if (OB_UNLIKELY(pl_routine_obj_ != nullptr)) {
|
||||
@ -888,7 +892,7 @@ int ObPLObjectSet::inner_add_cache_obj(ObILibCacheCtx &ctx,
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
ObPLCacheCtx& pc_ctx = static_cast<ObPLCacheCtx&>(ctx);
|
||||
pl::ObPLCompileUnit *cache_object = static_cast<pl::ObPLCompileUnit *>(cache_obj);
|
||||
pl::ObPLCacheObject *cache_object = static_cast<pl::ObPLCacheObject *>(cache_obj);
|
||||
ObSEArray<PCVPlSchemaObj, 4> schema_array;
|
||||
|
||||
if (OB_ISNULL(cache_object)) {
|
||||
@ -897,14 +901,15 @@ int ObPLObjectSet::inner_add_cache_obj(ObILibCacheCtx &ctx,
|
||||
} else if (OB_UNLIKELY(!cache_object->is_prcr() &&
|
||||
!cache_object->is_sfc() &&
|
||||
!cache_object->is_pkg() &&
|
||||
!cache_object->is_anon())) {
|
||||
!cache_object->is_anon() &&
|
||||
!cache_object->is_call_stmt())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("cache object is invalid", K(cache_object));
|
||||
} else if (OB_FAIL(ObPLObjectValue::get_all_dep_schema(*pc_ctx.schema_guard_,
|
||||
cache_object->get_dependency_table(),
|
||||
schema_array))) {
|
||||
LOG_WARN("failed to get all dep schema", K(ret));
|
||||
} else {
|
||||
} else {
|
||||
DLIST_FOREACH(pl_object_value, object_value_sets_) {
|
||||
bool is_same = true;
|
||||
bool is_old_version = false;
|
||||
|
@ -21,16 +21,12 @@
|
||||
#include "sql/plan_cache/ob_cache_object_factory.h"
|
||||
#include "sql/plan_cache/ob_lib_cache_register.h"
|
||||
#include "pl/ob_pl.h"
|
||||
#include "pl/pl_cache/ob_pl_cache_object.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
|
||||
|
||||
namespace pl
|
||||
{
|
||||
class ObPLCompileUnit;
|
||||
}
|
||||
|
||||
namespace pl
|
||||
{
|
||||
|
||||
@ -156,6 +152,7 @@ struct ObPLObjectKey : public ObILibCacheKey
|
||||
common::ObString name_;
|
||||
};
|
||||
|
||||
|
||||
class ObPLObjectValue : public common::ObDLinkBase<ObPLObjectValue>
|
||||
{
|
||||
public:
|
||||
@ -241,7 +238,7 @@ public:
|
||||
common::ObFixedArray<PCVPlSchemaObj *, common::ObIAllocator> stored_schema_objs_;
|
||||
common::Ob2DArray<ObParamInfo, common::OB_MALLOC_BIG_BLOCK_SIZE,
|
||||
common::ObWrapperAllocator, false> params_info_;
|
||||
pl::ObPLCompileUnit *pl_routine_obj_;
|
||||
pl::ObPLCacheObject *pl_routine_obj_;
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObPLObjectValue);
|
||||
};
|
||||
|
@ -54,7 +54,8 @@ int ObPLCacheMgr::get_pl_object(ObPlanCache *lib_cache, ObILibCacheCtx &ctx, ObC
|
||||
(!guard.get_cache_obj()->is_prcr() &&
|
||||
!guard.get_cache_obj()->is_sfc() &&
|
||||
!guard.get_cache_obj()->is_pkg() &&
|
||||
!guard.get_cache_obj()->is_anon())) {
|
||||
!guard.get_cache_obj()->is_anon() &&
|
||||
guard.get_cache_obj()->get_ns() != ObLibCacheNameSpace::NS_CALLSTMT)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
PL_CACHE_LOG(WARN, "cache obj is invalid", KPC(guard.get_cache_obj()));
|
||||
}
|
||||
@ -89,7 +90,8 @@ int ObPLCacheMgr::get_pl_cache(ObPlanCache *lib_cache, ObCacheObjGuard& guard, O
|
||||
// update pl func/package stat
|
||||
pl::PLCacheObjStat *stat = NULL;
|
||||
int64_t current_time = ObTimeUtility::current_time();
|
||||
if (ObLibCacheNameSpace::NS_PKG != guard.get_cache_obj()->get_ns()) {
|
||||
if (ObLibCacheNameSpace::NS_PKG != guard.get_cache_obj()->get_ns() &&
|
||||
ObLibCacheNameSpace::NS_CALLSTMT != guard.get_cache_obj()->get_ns()) {
|
||||
pl::ObPLFunction* pl_func = static_cast<pl::ObPLFunction*>(guard.get_cache_obj());
|
||||
stat = &pl_func->get_stat_for_update();
|
||||
ATOMIC_INC(&(stat->hit_count_));
|
||||
@ -156,7 +158,8 @@ int ObPLCacheMgr::add_pl_cache(ObPlanCache *lib_cache, ObILibCacheObject *pl_obj
|
||||
}
|
||||
break;
|
||||
case NS_PKG:
|
||||
case NS_ANON: {
|
||||
case NS_ANON:
|
||||
case NS_CALLSTMT: {
|
||||
ns = pl_object->get_ns();
|
||||
}
|
||||
break;
|
||||
|
@ -45,7 +45,8 @@ struct ObGetPLKVEntryOp : public sql::ObKVEntryTraverseOp
|
||||
if (ObLibCacheNameSpace::NS_PRCR == entry.first->namespace_ ||
|
||||
ObLibCacheNameSpace::NS_SFC == entry.first->namespace_ ||
|
||||
ObLibCacheNameSpace::NS_ANON == entry.first->namespace_ ||
|
||||
ObLibCacheNameSpace::NS_PKG == entry.first->namespace_) {
|
||||
ObLibCacheNameSpace::NS_PKG == entry.first->namespace_ ||
|
||||
ObLibCacheNameSpace::NS_CALLSTMT == entry.first->namespace_) {
|
||||
is_match = true;
|
||||
}
|
||||
return ret;
|
||||
|
78
src/pl/pl_cache/ob_pl_cache_object.cpp
Normal file
78
src/pl/pl_cache/ob_pl_cache_object.cpp
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX PL_CACHE
|
||||
#include "ob_pl_cache_object.h"
|
||||
#include "lib/oblog/ob_log_module.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace pl
|
||||
{
|
||||
|
||||
void ObPLCacheObject::reset()
|
||||
{
|
||||
ObILibCacheObject::reset();
|
||||
tenant_schema_version_ = OB_INVALID_VERSION;
|
||||
sys_schema_version_ = OB_INVALID_VERSION;
|
||||
params_info_.reset();
|
||||
sql_expression_factory_.destroy();
|
||||
expr_operator_factory_.destroy();
|
||||
expressions_.reset();
|
||||
}
|
||||
|
||||
int ObPLCacheObject::set_params_info(const ParamStore ¶ms)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t N = params.count();
|
||||
sql::ObParamInfo param_info;
|
||||
if (N > 0 && OB_FAIL(params_info_.reserve(N))) {
|
||||
OB_LOG(WARN, "fail to reserve params info", K(ret));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < N; ++i) {
|
||||
param_info.flag_ = params.at(i).get_param_flag();
|
||||
param_info.type_ = params.at(i).get_param_meta().get_type();
|
||||
param_info.col_type_ = params.at(i).get_collation_type();
|
||||
if (sql::ObSQLUtils::is_oracle_empty_string(params.at(i))) {
|
||||
param_info.is_oracle_empty_string_ = true;
|
||||
}
|
||||
if (params.at(i).get_param_meta().get_type() != params.at(i).get_type()) {
|
||||
LOG_TRACE("differ in set_params_info",
|
||||
K(params.at(i).get_param_meta().get_type()),
|
||||
K(params.at(i).get_type()),
|
||||
K(common::lbt()));
|
||||
}
|
||||
//todo:it is for arraybinding check, not pl ext check
|
||||
if (params.at(i).is_ext()) {
|
||||
ObDataType data_type;
|
||||
if (OB_FAIL(sql::ObSQLUtils::get_ext_obj_data_type(params.at(i), data_type))) {
|
||||
LOG_WARN("fail to get ext obj data type", K(ret));
|
||||
} else {
|
||||
param_info.ext_real_type_ = data_type.get_obj_type();
|
||||
param_info.scale_ = data_type.get_meta_type().get_scale();
|
||||
}
|
||||
LOG_DEBUG("ext params info", K(data_type), K(param_info), K(params.at(i)));
|
||||
} else {
|
||||
param_info.scale_ = params.at(i).get_scale();
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(params_info_.push_back(param_info))) {
|
||||
LOG_WARN("failed to push back param info", K(ret));
|
||||
}
|
||||
}
|
||||
param_info.reset();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
101
src/pl/pl_cache/ob_pl_cache_object.h
Normal file
101
src/pl/pl_cache/ob_pl_cache_object.h
Normal file
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright (c) 2022 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_PL_CACHE_OBJECT_H_
|
||||
#define OCEANBASE_PL_CACHE_OBJECT_H_
|
||||
#include "share/ob_define.h"
|
||||
#include "sql/plan_cache/ob_i_lib_cache_object.h"
|
||||
#include "sql/plan_cache/ob_i_lib_cache_context.h"
|
||||
#include "sql/plan_cache/ob_cache_object_factory.h"
|
||||
#include "sql/plan_cache/ob_lib_cache_register.h"
|
||||
#include "sql/plan_cache/ob_cache_object.h"
|
||||
#include "sql/engine/expr/ob_sql_expression_factory.h"
|
||||
#include "sql/resolver/expr/ob_raw_expr.h"
|
||||
#include "sql/engine/expr/ob_sql_expression.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
|
||||
|
||||
namespace pl
|
||||
{
|
||||
|
||||
class ObPLCacheObject : public sql::ObILibCacheObject
|
||||
{
|
||||
public:
|
||||
ObPLCacheObject(sql::ObLibCacheNameSpace ns, lib::MemoryContext &mem_context)
|
||||
: ObILibCacheObject(ns, mem_context),
|
||||
tenant_schema_version_(OB_INVALID_VERSION),
|
||||
sys_schema_version_(OB_INVALID_VERSION),
|
||||
dependency_tables_(allocator_),
|
||||
params_info_( (ObWrapperAllocator(allocator_)) ),
|
||||
expr_factory_(allocator_),
|
||||
sql_expression_factory_(allocator_),
|
||||
expr_operator_factory_(allocator_),
|
||||
expressions_(allocator_),
|
||||
expr_op_size_(0),
|
||||
frame_info_(allocator_)
|
||||
{}
|
||||
|
||||
virtual ~ObPLCacheObject() {}
|
||||
virtual void reset();
|
||||
inline bool is_call_stmt() const { return sql::ObLibCacheNameSpace::NS_CALLSTMT == ns_; }
|
||||
|
||||
inline void set_sys_schema_version(int64_t schema_version) { sys_schema_version_ = schema_version; }
|
||||
inline void set_tenant_schema_version(int64_t schema_version) { tenant_schema_version_ = schema_version; }
|
||||
inline int64_t get_tenant_schema_version() const { return tenant_schema_version_; }
|
||||
inline int64_t get_sys_schema_version() const { return sys_schema_version_; }
|
||||
|
||||
inline int64_t get_dependency_table_size() const { return dependency_tables_.count(); }
|
||||
inline const sql::DependenyTableStore &get_dependency_table() const { return dependency_tables_; }
|
||||
int init_dependency_table_store(int64_t dependency_table_cnt) { return dependency_tables_.init(dependency_table_cnt); }
|
||||
inline sql::DependenyTableStore &get_dependency_table() { return dependency_tables_; }
|
||||
int set_params_info(const ParamStore ¶ms);
|
||||
const common::Ob2DArray<sql::ObParamInfo,
|
||||
common::OB_MALLOC_BIG_BLOCK_SIZE,
|
||||
common::ObWrapperAllocator, false> &get_params_info() const { return params_info_; }
|
||||
|
||||
inline sql::ObRawExprFactory &get_expr_factory() { return expr_factory_; }
|
||||
inline sql::ObSqlExpressionFactory &get_sql_expression_factory() { return sql_expression_factory_; }
|
||||
inline sql::ObExprOperatorFactory &get_expr_operator_factory() { return expr_operator_factory_; }
|
||||
inline const common::ObIArray<sql::ObSqlExpression*> &get_expressions() const { return expressions_; }
|
||||
inline common::ObIArray<sql::ObSqlExpression*> &get_expressions() { return expressions_; }
|
||||
inline int set_expressions(common::ObIArray<sql::ObSqlExpression*> &exprs) { return expressions_.assign(exprs); }
|
||||
inline int64_t get_expr_op_size() const { return expr_op_size_; }
|
||||
inline void set_expr_op_size(int64_t size) { expr_op_size_ = size; }
|
||||
inline sql::ObExprFrameInfo &get_frame_info() { return frame_info_; }
|
||||
|
||||
TO_STRING_KV(K_(expr_op_size),
|
||||
K_(tenant_schema_version),
|
||||
K_(sys_schema_version),
|
||||
K_(dependency_tables));
|
||||
|
||||
protected:
|
||||
int64_t tenant_schema_version_;
|
||||
int64_t sys_schema_version_;
|
||||
sql::DependenyTableStore dependency_tables_;
|
||||
// stored args information after paramalization
|
||||
common::Ob2DArray<sql::ObParamInfo,
|
||||
common::OB_MALLOC_BIG_BLOCK_SIZE,
|
||||
common::ObWrapperAllocator, false> params_info_;
|
||||
sql::ObRawExprFactory expr_factory_;
|
||||
sql::ObSqlExpressionFactory sql_expression_factory_;
|
||||
sql::ObExprOperatorFactory expr_operator_factory_;
|
||||
common::ObFixedArray<sql::ObSqlExpression*, common::ObIAllocator> expressions_;
|
||||
int64_t expr_op_size_;
|
||||
sql::ObExprFrameInfo frame_info_;
|
||||
};
|
||||
|
||||
} // namespace pl end
|
||||
} // namespace oceanbase end
|
||||
|
||||
#endif
|
@ -305,6 +305,27 @@ int ObDBMSSession::set_identifier(sql::ObExecContext &ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObDBMSSession::reset_package(sql::ObExecContext &ctx,
|
||||
sql::ParamStore ¶ms,
|
||||
common::ObObj &result)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
sql::ObSQLSessionInfo *session = ctx.get_my_session();
|
||||
ObPLContext *pl_ctx = nullptr;
|
||||
ObString client_id;
|
||||
if (OB_UNLIKELY(OB_ISNULL(session))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("session info is nullptr", K(ret));
|
||||
} else if (OB_UNLIKELY(0 != params.count())) {
|
||||
ObString func_name("RESET_PACKAGE");
|
||||
ret = OB_ERR_WRONG_FUNC_ARGUMENTS_TYPE;
|
||||
LOG_USER_ERROR(OB_ERR_WRONG_FUNC_ARGUMENTS_TYPE, func_name.length(), func_name.ptr());
|
||||
} else {
|
||||
session->set_need_reset_package(true);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObDBMSSession::check_argument(const ObObj &input_param, bool allow_null,
|
||||
bool need_case_up, int32_t param_idx,
|
||||
int64_t max_len, ObString &output_param)
|
||||
|
@ -34,6 +34,8 @@ public:
|
||||
sql::ObExecContext &ctx, sql::ParamStore ¶ms, common::ObObj &result);
|
||||
static int set_identifier(
|
||||
sql::ObExecContext &ctx, sql::ParamStore ¶ms, common::ObObj &result);
|
||||
static int reset_package(
|
||||
sql::ObExecContext &ctx, sql::ParamStore ¶ms, common::ObObj &result);
|
||||
private:
|
||||
static int check_argument(const ObObj &input_param, bool allow_null,
|
||||
bool need_case_up, int32_t param_idx,
|
||||
|
@ -175,8 +175,17 @@ int ObDbmsInfo::set_bind_param(const ObString ¶m_name, const ObObjParam¶
|
||||
}
|
||||
|
||||
if (OB_INVALID_INDEX != idx) {
|
||||
OZ (ob_write_obj(alloc, param_value, bind_params_.at(idx).param_value_),
|
||||
param_name, param_value);
|
||||
if (param_value.is_pl_extend()
|
||||
&& param_value.get_ext() != 0
|
||||
&& param_value.get_meta().get_extend_type() != PL_REF_CURSOR_TYPE) {
|
||||
if (bind_params_.at(idx).param_value_.get_ext() != 0) {
|
||||
OZ (ObUserDefinedType::destruct_obj(bind_params_.at(idx).param_value_));
|
||||
}
|
||||
OZ (ObUserDefinedType::deep_copy_obj(alloc, param_value, bind_params_.at(idx).param_value_));
|
||||
} else {
|
||||
OZ (ob_write_obj(alloc, param_value, bind_params_.at(idx).param_value_),
|
||||
param_name, param_value);
|
||||
}
|
||||
OX (bind_params_.at(idx).param_value_.set_accuracy(param_value.get_accuracy()));
|
||||
OX (bind_params_.at(idx).param_value_.set_param_meta());
|
||||
} else {
|
||||
@ -184,7 +193,13 @@ int ObDbmsInfo::set_bind_param(const ObString ¶m_name, const ObObjParam¶
|
||||
ObObj clone_value;
|
||||
BindParam clone_param;
|
||||
OZ (ob_write_string(alloc, param_name, clone_name), param_name, param_value);
|
||||
OZ (ob_write_obj(alloc, param_value, clone_value), param_name, param_value);
|
||||
if (param_value.is_pl_extend()
|
||||
&& param_value.get_ext() != 0
|
||||
&& param_value.get_meta().get_extend_type() != PL_REF_CURSOR_TYPE) {
|
||||
OZ (ObUserDefinedType::deep_copy_obj(alloc, param_value, clone_value));
|
||||
} else {
|
||||
OZ (ob_write_obj(alloc, param_value, clone_value), param_name, param_value);
|
||||
}
|
||||
OX (clone_param = BindParam(clone_name, clone_value));
|
||||
OX (clone_param.param_value_.set_accuracy(param_value.get_accuracy()));
|
||||
OX (clone_param.param_value_.set_param_meta());
|
||||
@ -288,16 +303,17 @@ int ObDbmsCursorInfo::parse(const ObString &sql_stmt, ObSQLSessionInfo &session)
|
||||
char **param_names = NULL;
|
||||
ObString clone_name;
|
||||
// 解析语句
|
||||
OZ (parser.parse(sql_stmt, parse_result, DBMS_SQL_MODE), sql_stmt);
|
||||
if (OB_FAIL(parser.parse(sql_stmt, parse_result, DBMS_SQL_MODE))) {
|
||||
LOG_WARN("failed to parse sql_stmt", K(sql_stmt), K(ret));
|
||||
int64_t error_offset =
|
||||
parse_result.start_col_ > 0 ? (parse_result.start_col_ - 1) : 0;
|
||||
session.get_warnings_buffer().set_error_line_column(0, error_offset);
|
||||
}
|
||||
OZ (ObResolverUtils::resolve_stmt_type(parse_result, stmt_type_), sql_stmt);
|
||||
// cann't execute multi select stmt
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (ObStmt::is_ddl_stmt(stmt_type_, true)) {
|
||||
ret = OB_NO_STMT_PARSE;
|
||||
LOG_WARN("dbms_cursor need parse a select stmt.", K(ret));
|
||||
} else if (ObStmt::is_select_stmt(stmt_type_)
|
||||
&& !parser.is_pl_stmt(sql_stmt)
|
||||
&& !parser.is_single_stmt(sql_stmt)) {
|
||||
if (OB_SUCC(ret)
|
||||
&& !parser.is_pl_stmt(sql_stmt)
|
||||
&& !parser.is_single_stmt(sql_stmt)) {
|
||||
ret = OB_ERR_CMD_NOT_PROPERLY_ENDED;
|
||||
LOG_WARN("execute immdeidate only support one stmt", K(ret));
|
||||
}
|
||||
@ -318,6 +334,30 @@ int ObDbmsCursorInfo::parse(const ObString &sql_stmt, ObSQLSessionInfo &session)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t ObDbmsCursorInfo::get_dbms_id()
|
||||
{
|
||||
int64_t id = -1;
|
||||
if (0 == (get_id() & CANDIDATE_CURSOR_ID)) {
|
||||
// ps cursor id
|
||||
id = get_id();
|
||||
} else {
|
||||
id = get_id() - CANDIDATE_CURSOR_ID;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
int64_t ObDbmsCursorInfo::convert_to_dbms_cursor_id(int64_t id)
|
||||
{
|
||||
int64_t new_id = -1;
|
||||
if (1 == (id & CANDIDATE_CURSOR_ID)) {
|
||||
// ps cursor id
|
||||
new_id = id;
|
||||
} else {
|
||||
new_id = id + CANDIDATE_CURSOR_ID;
|
||||
}
|
||||
return new_id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -169,6 +169,17 @@ private:
|
||||
|
||||
class ObDbmsCursorInfo : public ObPLCursorInfo, public ObDbmsInfo
|
||||
{
|
||||
public:
|
||||
// cursor id in OB
|
||||
/* ps cursor : always equal with stmt id, always smaller than candidate_cursor_id_
|
||||
* ref cursor : always start with CANDIDATE_CURSOR_ID, user can't get ref cursor id by SQL
|
||||
* only client and server use the id when interacting
|
||||
* dbms sql cursor : always start with CANDIDATE_CURSOR_ID, user can get cursor id by SQL
|
||||
* CANDIDATE_CURSOR_ID may be out of precision.
|
||||
* so we should use get_dbms_id and convert_to_dbms_cursor_id to provide a vaild id for user
|
||||
*/
|
||||
static const int64_t CANDIDATE_CURSOR_ID = 1LL << 31;
|
||||
|
||||
public:
|
||||
ObDbmsCursorInfo(common::ObIAllocator &alloc)
|
||||
: ObPLCursorInfo(true),
|
||||
@ -189,6 +200,8 @@ public:
|
||||
int64_t get_affected_rows() const { return affected_rows_; }
|
||||
int prepare_entity(sql::ObSQLSessionInfo &session);
|
||||
int64_t search_array(const ObString &name, ObIArray<ObString> &array);
|
||||
int64_t get_dbms_id();
|
||||
static int64_t convert_to_dbms_cursor_id(int64_t id);
|
||||
|
||||
private:
|
||||
// affected_rows_ 在每次 open 都会被重置
|
||||
|
@ -8606,39 +8606,37 @@ int ObDDLOperator::create_trigger(ObTriggerInfo &trigger_info,
|
||||
ObErrorInfo &error_info,
|
||||
ObIArray<ObDependencyInfo> &dep_infos,
|
||||
const ObString *ddl_stmt_str,
|
||||
bool for_insert_errors,
|
||||
bool is_update_table_schema_version,
|
||||
bool is_for_truncate_table)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
//for_insert_errors is false: create trigger normally
|
||||
//for_insert_errors is true: Insert error information into the system table after the trigger is built so the following steps can be skipped
|
||||
if (!for_insert_errors) {
|
||||
ObSchemaService *schema_service = schema_service_.get_schema_service();
|
||||
const uint64_t tenant_id = trigger_info.get_tenant_id();
|
||||
int64_t new_schema_version = OB_INVALID_VERSION;
|
||||
bool is_replace = false;
|
||||
OV (OB_NOT_NULL(schema_service));
|
||||
if (!is_for_truncate_table) {
|
||||
// If create_trigger through truncate table, trigger_info already has its own trigger_id.
|
||||
// but there is no such trigger in the internal table at this time, so is_replace must be false
|
||||
OX (is_replace = (OB_INVALID_ID != trigger_info.get_trigger_id()));
|
||||
if (!is_replace) {
|
||||
OZ (fill_trigger_id(*schema_service, trigger_info), trigger_info.get_trigger_name());
|
||||
}
|
||||
}
|
||||
OZ (schema_service_.gen_new_schema_version(tenant_id, new_schema_version),
|
||||
tenant_id, trigger_info.get_trigger_name());
|
||||
OX (trigger_info.set_schema_version(new_schema_version));
|
||||
OZ (schema_service->get_trigger_sql_service().create_trigger(trigger_info, is_replace,
|
||||
trans, ddl_stmt_str),
|
||||
trigger_info.get_trigger_name(), is_replace);
|
||||
if (!trigger_info.is_system_type() && is_update_table_schema_version) {
|
||||
uint64_t base_table_id = trigger_info.get_base_object_id();
|
||||
OZ (schema_service->get_table_sql_service().update_data_table_schema_version(
|
||||
trans, tenant_id, base_table_id, false/*in offline ddl white list*/),
|
||||
base_table_id, trigger_info.get_trigger_name());
|
||||
|
||||
ObSchemaService *schema_service = schema_service_.get_schema_service();
|
||||
const uint64_t tenant_id = trigger_info.get_tenant_id();
|
||||
int64_t new_schema_version = OB_INVALID_VERSION;
|
||||
bool is_replace = false;
|
||||
OV (OB_NOT_NULL(schema_service));
|
||||
if (!is_for_truncate_table) {
|
||||
// If create_trigger through truncate table, trigger_info already has its own trigger_id.
|
||||
// but there is no such trigger in the internal table at this time, so is_replace must be false
|
||||
OX (is_replace = (OB_INVALID_ID != trigger_info.get_trigger_id()));
|
||||
if (!is_replace) {
|
||||
OZ (fill_trigger_id(*schema_service, trigger_info), trigger_info.get_trigger_name());
|
||||
}
|
||||
}
|
||||
OZ (schema_service_.gen_new_schema_version(tenant_id, new_schema_version),
|
||||
tenant_id, trigger_info.get_trigger_name());
|
||||
OX (trigger_info.set_schema_version(new_schema_version));
|
||||
OZ (schema_service->get_trigger_sql_service().create_trigger(trigger_info, is_replace,
|
||||
trans, ddl_stmt_str),
|
||||
trigger_info.get_trigger_name(), is_replace);
|
||||
if (!trigger_info.is_system_type() && is_update_table_schema_version) {
|
||||
uint64_t base_table_id = trigger_info.get_base_object_id();
|
||||
OZ (schema_service->get_table_sql_service().update_data_table_schema_version(
|
||||
trans, tenant_id, base_table_id, false/*in offline ddl white list*/),
|
||||
base_table_id, trigger_info.get_trigger_name());
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (0 == dep_infos.count()) {
|
||||
// create trigger in mysql mode or create trigger when truncate table, dep_infos.count() is 0,
|
||||
// no need to deal with dependencies.
|
||||
|
@ -793,7 +793,6 @@ public:
|
||||
share::schema::ObErrorInfo &error_info,
|
||||
ObIArray<ObDependencyInfo> &dep_infos,
|
||||
const common::ObString *ddl_stmt_str/*=NULL*/,
|
||||
bool for_insert_errors,
|
||||
bool is_update_table_schema_version = true,
|
||||
bool is_for_truncate_table = false);
|
||||
// set ddl_stmt_str to NULL if the statement is not 'drop trigger xxx'.
|
||||
|
@ -14703,7 +14703,7 @@ int ObDDLService::rebuild_triggers_on_hidden_table(
|
||||
if (OB_SUCC(ret)) {
|
||||
ObSEArray<ObDependencyInfo, 1> dep_infos;
|
||||
OZ (ddl_operator.create_trigger(new_trigger_info, trans, error_info, dep_infos,
|
||||
nullptr, false/*for_insert_errors*/, false/*is_update_table_schema_version*/));
|
||||
nullptr, false/*is_update_table_schema_version*/));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -28202,7 +28202,7 @@ int ObDDLService::create_trigger(const ObCreateTriggerArg &arg)
|
||||
int ret = OB_SUCCESS;
|
||||
ObSchemaGetterGuard schema_guard;
|
||||
ObTriggerInfo new_trigger_info;
|
||||
//for_insert_errors_ is false, Indicates that the trigger is created normally
|
||||
//in_second_stage_ is false, Indicates that the trigger is created normally
|
||||
//true Indicates that the error message is inserted into the system table after the trigger is created
|
||||
//So the following steps can be skipped
|
||||
uint64_t tenant_id = OB_INVALID_ID;
|
||||
@ -28217,7 +28217,7 @@ int ObDDLService::create_trigger(const ObCreateTriggerArg &arg)
|
||||
} else if (FALSE_IT(tenant_id = new_trigger_info.get_tenant_id())) {
|
||||
} else if (OB_FAIL(get_tenant_schema_guard_with_version_in_inner_table(tenant_id, schema_guard))) {
|
||||
LOG_WARN("o get schema guard in inner table failed", KR(ret), K(tenant_id));
|
||||
} else if (!arg.for_insert_errors_) {
|
||||
} else {
|
||||
const ObTriggerInfo *old_trigger_info = NULL;
|
||||
if (!arg.is_valid()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
@ -28245,7 +28245,7 @@ int ObDDLService::create_trigger(const ObCreateTriggerArg &arg)
|
||||
const_cast<ObErrorInfo &>(arg.error_info_),
|
||||
const_cast<ObSArray<ObDependencyInfo> &>(arg.dependency_infos_),
|
||||
&arg.ddl_stmt_str_,
|
||||
arg.for_insert_errors_,
|
||||
arg.in_second_stage_,
|
||||
schema_guard))) {
|
||||
LOG_WARN("create trigger in trans failed", K(ret));
|
||||
}
|
||||
@ -28256,7 +28256,7 @@ int ObDDLService::create_trigger_in_trans(ObTriggerInfo &trigger_info,
|
||||
ObErrorInfo &error_info,
|
||||
ObIArray<ObDependencyInfo> &dep_infos,
|
||||
const ObString *ddl_stmt_str,
|
||||
bool for_insert_errors,
|
||||
bool in_second_stage,
|
||||
share::schema::ObSchemaGetterGuard &schema_guard)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -28269,10 +28269,10 @@ int ObDDLService::create_trigger_in_trans(ObTriggerInfo &trigger_info,
|
||||
} else if (OB_FAIL(trans.start(sql_proxy_, tenant_id, refreshed_schema_version))) {
|
||||
LOG_WARN("start transaction failed", KR(ret), K(tenant_id), K(refreshed_schema_version));
|
||||
}
|
||||
if (OB_SUCC(ret) && !for_insert_errors) {
|
||||
if (OB_SUCC(ret) && !in_second_stage) {
|
||||
OZ (adjust_trigger_action_order(schema_guard, trans, ddl_operator, trigger_info, true));
|
||||
}
|
||||
OZ (ddl_operator.create_trigger(trigger_info, trans, error_info, dep_infos, ddl_stmt_str, for_insert_errors));
|
||||
OZ (ddl_operator.create_trigger(trigger_info, trans, error_info, dep_infos, ddl_stmt_str));
|
||||
if (trans.is_started()) {
|
||||
int temp_ret = OB_SUCCESS;
|
||||
if (OB_SUCCESS != (temp_ret = trans.end(OB_SUCC(ret)))) {
|
||||
@ -28527,7 +28527,6 @@ int ObDDLService::create_trigger_for_truncate_table(ObSchemaGetterGuard &schema_
|
||||
ObSEArray<ObDependencyInfo, 1> dep_infos;
|
||||
if (OB_FAIL(ddl_operator.create_trigger(new_trigger_info, trans, error_info, dep_infos,
|
||||
&origin_trigger_info->get_trigger_body(),
|
||||
false, /* for_insert_error */
|
||||
is_update_table_schema_version,
|
||||
true))) {
|
||||
LOG_WARN("failed to create trigger for truncate table", K(ret));
|
||||
|
@ -736,6 +736,25 @@ int ObInnerTableSchema::all_virtual_trigger_schema(ObTableSchema &table_schema)
|
||||
false, //is_nullable
|
||||
false); //is_autoincrement
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObObj analyze_flag_default;
|
||||
analyze_flag_default.set_int(0);
|
||||
ADD_COLUMN_SCHEMA_T("analyze_flag", //column_name
|
||||
++column_id, //column_id
|
||||
0, //rowkey_id
|
||||
0, //index_id
|
||||
0, //part_key_pos
|
||||
ObIntType, //column_type
|
||||
CS_TYPE_INVALID, //column_collation_type
|
||||
sizeof(int64_t), //column_length
|
||||
-1, //column_precision
|
||||
-1, //column_scale
|
||||
false, //is_nullable
|
||||
false, //is_autoincrement
|
||||
analyze_flag_default,
|
||||
analyze_flag_default); //default_value
|
||||
}
|
||||
table_schema.set_index_using_type(USING_BTREE);
|
||||
table_schema.set_row_store_type(ENCODING_ROW_STORE);
|
||||
table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL);
|
||||
@ -1262,6 +1281,25 @@ int ObInnerTableSchema::all_virtual_trigger_history_schema(ObTableSchema &table_
|
||||
true, //is_nullable
|
||||
false); //is_autoincrement
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObObj analyze_flag_default;
|
||||
analyze_flag_default.set_int(0);
|
||||
ADD_COLUMN_SCHEMA_T("analyze_flag", //column_name
|
||||
++column_id, //column_id
|
||||
0, //rowkey_id
|
||||
0, //index_id
|
||||
0, //part_key_pos
|
||||
ObIntType, //column_type
|
||||
CS_TYPE_INVALID, //column_collation_type
|
||||
sizeof(int64_t), //column_length
|
||||
-1, //column_precision
|
||||
-1, //column_scale
|
||||
true, //is_nullable
|
||||
false, //is_autoincrement
|
||||
analyze_flag_default,
|
||||
analyze_flag_default); //default_value
|
||||
}
|
||||
table_schema.set_index_using_type(USING_BTREE);
|
||||
table_schema.set_row_store_type(ENCODING_ROW_STORE);
|
||||
table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL);
|
||||
|
@ -4481,6 +4481,21 @@ int ObInnerTableSchema::all_virtual_tenant_trigger_sys_agent_schema(ObTableSchem
|
||||
false); //is_autoincrement
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ADD_COLUMN_SCHEMA("ANALYZE_FLAG", //column_name
|
||||
++column_id, //column_id
|
||||
0, //rowkey_id
|
||||
0, //index_id
|
||||
0, //part_key_pos
|
||||
ObNumberType, //column_type
|
||||
CS_TYPE_INVALID, //column_collation_type
|
||||
38, //column_length
|
||||
38, //column_precision
|
||||
0, //column_scale
|
||||
false, //is_nullable
|
||||
false); //is_autoincrement
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ADD_COLUMN_SCHEMA("GMT_CREATE", //column_name
|
||||
++column_id, //column_id
|
||||
|
@ -1524,6 +1524,21 @@ int ObInnerTableSchema::all_virtual_tenant_trigger_real_agent_ora_schema(ObTable
|
||||
false); //is_autoincrement
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ADD_COLUMN_SCHEMA("ANALYZE_FLAG", //column_name
|
||||
++column_id, //column_id
|
||||
0, //rowkey_id
|
||||
0, //index_id
|
||||
0, //part_key_pos
|
||||
ObNumberType, //column_type
|
||||
CS_TYPE_INVALID, //column_collation_type
|
||||
38, //column_length
|
||||
38, //column_precision
|
||||
0, //column_scale
|
||||
false, //is_nullable
|
||||
false); //is_autoincrement
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ADD_COLUMN_SCHEMA("GMT_CREATE", //column_name
|
||||
++column_id, //column_id
|
||||
|
@ -1547,6 +1547,25 @@ int ObInnerTableSchema::all_tenant_trigger_schema(ObTableSchema &table_schema)
|
||||
false, //is_nullable
|
||||
false); //is_autoincrement
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObObj analyze_flag_default;
|
||||
analyze_flag_default.set_int(0);
|
||||
ADD_COLUMN_SCHEMA_T("analyze_flag", //column_name
|
||||
++column_id, //column_id
|
||||
0, //rowkey_id
|
||||
0, //index_id
|
||||
0, //part_key_pos
|
||||
ObIntType, //column_type
|
||||
CS_TYPE_INVALID, //column_collation_type
|
||||
sizeof(int64_t), //column_length
|
||||
-1, //column_precision
|
||||
-1, //column_scale
|
||||
false, //is_nullable
|
||||
false, //is_autoincrement
|
||||
analyze_flag_default,
|
||||
analyze_flag_default); //default_value
|
||||
}
|
||||
table_schema.set_index_using_type(USING_BTREE);
|
||||
table_schema.set_row_store_type(ENCODING_ROW_STORE);
|
||||
table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL);
|
||||
@ -2089,6 +2108,25 @@ int ObInnerTableSchema::all_tenant_trigger_history_schema(ObTableSchema &table_s
|
||||
true, //is_nullable
|
||||
false); //is_autoincrement
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObObj analyze_flag_default;
|
||||
analyze_flag_default.set_int(0);
|
||||
ADD_COLUMN_SCHEMA_T("analyze_flag", //column_name
|
||||
++column_id, //column_id
|
||||
0, //rowkey_id
|
||||
0, //index_id
|
||||
0, //part_key_pos
|
||||
ObIntType, //column_type
|
||||
CS_TYPE_INVALID, //column_collation_type
|
||||
sizeof(int64_t), //column_length
|
||||
-1, //column_precision
|
||||
-1, //column_scale
|
||||
true, //is_nullable
|
||||
false, //is_autoincrement
|
||||
analyze_flag_default,
|
||||
analyze_flag_default); //default_value
|
||||
}
|
||||
table_schema.set_index_using_type(USING_BTREE);
|
||||
table_schema.set_row_store_type(ENCODING_ROW_STORE);
|
||||
table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL);
|
||||
|
@ -2247,6 +2247,7 @@ all_trigger_def = dict(
|
||||
('ref_trg_db_name', 'varchar:OB_MAX_TRIGGER_NAME_LENGTH', 'true'),
|
||||
('ref_trg_name', 'varchar:OB_MAX_TRIGGER_NAME_LENGTH', 'true'),
|
||||
('action_order', 'int', 'false'),
|
||||
('analyze_flag', 'int', 'false', 0),
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -5827,7 +5827,7 @@ public:
|
||||
K(base_object_name_),
|
||||
K(trigger_info_),
|
||||
K(with_replace_),
|
||||
K(for_insert_errors_),
|
||||
K(in_second_stage_),
|
||||
K(error_info_),
|
||||
K(dependency_infos_));
|
||||
public:
|
||||
@ -5841,7 +5841,7 @@ public:
|
||||
struct
|
||||
{
|
||||
uint32_t with_replace_:1;
|
||||
uint32_t for_insert_errors_:1;
|
||||
uint32_t in_second_stage_:1; // is second create trigger stage
|
||||
uint32_t reserved_:30;
|
||||
};
|
||||
};
|
||||
|
@ -80,6 +80,11 @@ enum ObRoutineFlag
|
||||
SP_FLAG_READS_SQL_DATA = 65536,
|
||||
SP_FLAG_MODIFIES_SQL_DATA = 131072,
|
||||
SP_FLAG_CONTAINS_SQL = 262144,
|
||||
SP_FLAG_WPS = SP_FLAG_CONTAINS_SQL * 2,
|
||||
SP_FLAG_RPS = SP_FLAG_WPS * 2,
|
||||
SP_FLAG_HAS_SEQUENCE = SP_FLAG_RPS * 2,
|
||||
SP_FLAG_HAS_OUT_PARAM = SP_FLAG_HAS_SEQUENCE * 2,
|
||||
SP_FLAG_EXTERNAL_STATE = SP_FLAG_HAS_OUT_PARAM * 2,
|
||||
};
|
||||
|
||||
namespace oceanbase
|
||||
@ -152,7 +157,16 @@ public:
|
||||
virtual bool is_modifies_sql_data() const = 0;
|
||||
virtual void set_contains_sql() = 0;
|
||||
virtual bool is_contains_sql() const = 0;
|
||||
|
||||
virtual bool is_wps() const = 0;
|
||||
virtual bool is_rps() const = 0;
|
||||
virtual bool is_has_sequence() const = 0;
|
||||
virtual bool is_has_out_param() const = 0;
|
||||
virtual bool is_external_state() const = 0;
|
||||
virtual void set_wps() = 0;
|
||||
virtual void set_rps() = 0;
|
||||
virtual void set_has_sequence() = 0;
|
||||
virtual void set_has_out_param() = 0;
|
||||
virtual void set_external_state() = 0;
|
||||
TO_STRING_EMPTY();
|
||||
};
|
||||
|
||||
@ -469,7 +483,26 @@ public:
|
||||
OB_INLINE void set_no_sql() { flag_ &= ~SP_FLAG_READS_SQL_DATA; flag_ &= ~SP_FLAG_MODIFIES_SQL_DATA; flag_ |= SP_FLAG_NO_SQL;}
|
||||
OB_INLINE void set_reads_sql_data() { flag_ &= ~SP_FLAG_NO_SQL; flag_ &= ~SP_FLAG_MODIFIES_SQL_DATA; flag_ |= SP_FLAG_READS_SQL_DATA;}
|
||||
OB_INLINE void set_modifies_sql_data() { flag_ &= ~SP_FLAG_NO_SQL; flag_ &= ~SP_FLAG_READS_SQL_DATA; flag_ |= SP_FLAG_MODIFIES_SQL_DATA;}
|
||||
OB_INLINE void set_contains_sql() { flag_ &= ~SP_FLAG_NO_SQL; flag_ &= ~SP_FLAG_READS_SQL_DATA; flag_ &= ~SP_FLAG_MODIFIES_SQL_DATA;}
|
||||
OB_INLINE void set_contains_sql()
|
||||
{
|
||||
flag_ &= ~SP_FLAG_NO_SQL;
|
||||
flag_ &= ~SP_FLAG_READS_SQL_DATA;
|
||||
flag_ &= ~SP_FLAG_MODIFIES_SQL_DATA;
|
||||
flag_ |= SP_FLAG_CONTAINS_SQL;
|
||||
}
|
||||
|
||||
|
||||
OB_INLINE bool is_wps() const { return SP_FLAG_WPS == (flag_ & SP_FLAG_WPS); }
|
||||
OB_INLINE bool is_rps() const { return SP_FLAG_RPS == (flag_ & SP_FLAG_RPS); }
|
||||
OB_INLINE bool is_has_sequence() const { return SP_FLAG_HAS_SEQUENCE == (flag_ & SP_FLAG_HAS_SEQUENCE); }
|
||||
OB_INLINE bool is_has_out_param() const { return SP_FLAG_HAS_OUT_PARAM == (flag_ & SP_FLAG_HAS_OUT_PARAM); }
|
||||
OB_INLINE bool is_external_state() const { return SP_FLAG_EXTERNAL_STATE == (flag_ & SP_FLAG_EXTERNAL_STATE); }
|
||||
|
||||
OB_INLINE void set_wps() { flag_ |= SP_FLAG_WPS;}
|
||||
OB_INLINE void set_rps() { flag_ |= SP_FLAG_RPS;}
|
||||
OB_INLINE void set_has_sequence() { flag_ |= SP_FLAG_HAS_SEQUENCE;}
|
||||
OB_INLINE void set_has_out_param() { flag_ |= SP_FLAG_HAS_OUT_PARAM;}
|
||||
OB_INLINE void set_external_state() { flag_ |= SP_FLAG_EXTERNAL_STATE;}
|
||||
|
||||
OB_INLINE bool is_aggregate() const { return SP_FLAG_AGGREGATE == (flag_ & SP_FLAG_AGGREGATE); }
|
||||
|
||||
|
@ -817,6 +817,107 @@ int ObSchemaGetterGuard::get_routine_infos_in_udt(
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObSchemaGetterGuard::get_routine_info_in_udt(const uint64_t tenant_id,
|
||||
const uint64_t udt_id,
|
||||
const uint64_t subprogram_id,
|
||||
const ObRoutineInfo *&routine_info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObSchemaMgr *mgr = NULL;
|
||||
routine_info = NULL;
|
||||
|
||||
ObArray<const ObSimpleRoutineSchema *> schemas;
|
||||
if (!check_inner_stat()) {
|
||||
ret = OB_INNER_STAT_ERROR;
|
||||
LOG_WARN("inner stat error", KR(ret));
|
||||
} else if (OB_INVALID_ID == tenant_id || OB_INVALID_ID == udt_id || OB_INVALID_ID == subprogram_id) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(udt_id), K(subprogram_id));
|
||||
} else if (OB_FAIL(check_tenant_schema_guard(tenant_id))) {
|
||||
LOG_WARN("fail to check tenant schema guard", KR(ret), K(tenant_id), K_(tenant_id));
|
||||
} else if (OB_FAIL(check_lazy_guard(tenant_id, mgr))) {
|
||||
LOG_WARN("fail to check lazy guard", KR(ret), K(tenant_id));
|
||||
} else if (OB_FAIL(mgr->routine_mgr_.get_routine_schemas_in_udt(tenant_id, udt_id, schemas))) {
|
||||
LOG_WARN("get routine schemas in package failed", KR(ret), K(tenant_id), K(udt_id));
|
||||
} else {
|
||||
bool is_break = false;
|
||||
FOREACH_CNT_X(schema, schemas, (OB_SUCC(ret) && !is_break)) {
|
||||
const ObSimpleRoutineSchema *tmp_schema = *schema;
|
||||
const ObRoutineInfo *sub_routine_info = NULL;
|
||||
if (OB_ISNULL(tmp_schema)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("NULL ptr", KR(ret), KP(tmp_schema));
|
||||
} else if (OB_FAIL(get_schema(ROUTINE_SCHEMA,
|
||||
tmp_schema->get_tenant_id(),
|
||||
tmp_schema->get_routine_id(),
|
||||
sub_routine_info,
|
||||
tmp_schema->get_schema_version()))) {
|
||||
LOG_WARN("get schema failed", KR(ret), K(tenant_id),
|
||||
"routine_id", tmp_schema->get_routine_id(),
|
||||
"schema_version", tmp_schema->get_schema_version());
|
||||
} else if (OB_ISNULL(sub_routine_info)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("routine info is null", KR(ret));
|
||||
} else if (subprogram_id == sub_routine_info->get_subprogram_id()) {
|
||||
routine_info = sub_routine_info;
|
||||
is_break = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObSchemaGetterGuard::get_routine_info_in_package(const uint64_t tenant_id,
|
||||
const uint64_t package_id,
|
||||
const uint64_t subprogram_id,
|
||||
const ObRoutineInfo *&routine_info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObSchemaMgr *mgr = NULL;
|
||||
routine_info = NULL;
|
||||
|
||||
ObArray<const ObSimpleRoutineSchema *> schemas;
|
||||
if (!check_inner_stat()) {
|
||||
ret = OB_INNER_STAT_ERROR;
|
||||
LOG_WARN("inner stat error", KR(ret));
|
||||
} else if (OB_INVALID_ID == tenant_id || OB_INVALID_ID == package_id || OB_INVALID_ID == subprogram_id) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid argument", KR(ret), K(tenant_id), K(package_id), K(subprogram_id));
|
||||
} else if (OB_FAIL(check_tenant_schema_guard(tenant_id))) {
|
||||
LOG_WARN("fail to check tenant schema guard", KR(ret), K(tenant_id), K_(tenant_id));
|
||||
} else if (OB_FAIL(check_lazy_guard(tenant_id, mgr))) {
|
||||
LOG_WARN("fail to check lazy guard", KR(ret), K(tenant_id));
|
||||
} else if (OB_FAIL(mgr->routine_mgr_.get_routine_schemas_in_package(tenant_id, package_id, schemas))) {
|
||||
LOG_WARN("get routine schemas in package failed", KR(ret), K(tenant_id), K(package_id));
|
||||
} else {
|
||||
bool is_break = false;
|
||||
FOREACH_CNT_X(schema, schemas, (OB_SUCC(ret) && !is_break)) {
|
||||
const ObSimpleRoutineSchema *tmp_schema = *schema;
|
||||
const ObRoutineInfo *sub_routine_info = NULL;
|
||||
if (OB_ISNULL(tmp_schema)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("NULL ptr", KR(ret), KP(tmp_schema));
|
||||
} else if (OB_FAIL(get_schema(ROUTINE_SCHEMA,
|
||||
tmp_schema->get_tenant_id(),
|
||||
tmp_schema->get_routine_id(),
|
||||
sub_routine_info,
|
||||
tmp_schema->get_schema_version()))) {
|
||||
LOG_WARN("get schema failed", KR(ret), K(tenant_id),
|
||||
"routine_id", tmp_schema->get_routine_id(),
|
||||
"schema_version", tmp_schema->get_schema_version());
|
||||
} else if (OB_ISNULL(sub_routine_info)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("routine info is null", KR(ret));
|
||||
} else if (subprogram_id == sub_routine_info->get_subprogram_id()) {
|
||||
routine_info = sub_routine_info;
|
||||
is_break = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObSchemaGetterGuard::get_routine_infos_in_package(
|
||||
const uint64_t tenant_id, const uint64_t package_id,
|
||||
common::ObIArray<const ObRoutineInfo *> &routine_infos)
|
||||
|
@ -312,9 +312,17 @@ public:
|
||||
int get_udt_infos_in_database(const uint64_t tenant_id,
|
||||
const uint64_t database_id,
|
||||
common::ObIArray<const ObUDTTypeInfo *> &udt_infos);
|
||||
int get_routine_info_in_udt(const uint64_t tenant_id,
|
||||
const uint64_t udt_id,
|
||||
const uint64_t subprogram_id,
|
||||
const ObRoutineInfo *&routine_info);
|
||||
int get_routine_infos_in_udt(const uint64_t tenant_id,
|
||||
const uint64_t udt_id,
|
||||
common::ObIArray<const ObRoutineInfo *> &routine_infos);
|
||||
int get_routine_info_in_package(const uint64_t tenant_id,
|
||||
const uint64_t package_id,
|
||||
const uint64_t subprogram_id,
|
||||
const ObRoutineInfo *&routine_info);
|
||||
int get_routine_infos_in_package(const uint64_t tenant_id,
|
||||
const uint64_t package_id,
|
||||
common::ObIArray<const ObRoutineInfo *> &routine_infos);
|
||||
|
@ -2186,6 +2186,7 @@ int ObSchemaRetrieveUtils::fill_trigger_schema(
|
||||
ObString default_value;
|
||||
int64_t order_type_defualt_value = 0;
|
||||
int64_t action_order_default_value = 1;
|
||||
uint64_t analyze_flag_default_value = 0;
|
||||
trigger_info.set_tenant_id(tenant_id);
|
||||
EXTRACT_INT_FIELD_TO_CLASS_MYSQL_WITH_TENANT_ID(result, trigger_id, trigger_info, tenant_id);
|
||||
EXTRACT_INT_FIELD_MYSQL(result, "is_deleted", is_deleted, bool);
|
||||
@ -2222,6 +2223,8 @@ int ObSchemaRetrieveUtils::fill_trigger_schema(
|
||||
true, true, default_value);
|
||||
EXTRACT_INT_FIELD_TO_CLASS_MYSQL_WITH_DEFAULT_VALUE(result, action_order, trigger_info, int64_t,
|
||||
false, true, action_order_default_value);
|
||||
EXTRACT_INT_FIELD_TO_CLASS_MYSQL_WITH_DEFAULT_VALUE(result, analyze_flag, trigger_info, uint64_t,
|
||||
true, true, analyze_flag_default_value);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -6890,6 +6890,26 @@ int ObTableSchema::has_before_update_row_trigger(ObSchemaGetterGuard &schema_gua
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableSchema::is_allow_parallel_of_trigger(ObSchemaGetterGuard &schema_guard,
|
||||
bool &is_forbid_parallel) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObTriggerInfo *trigger_info = NULL;
|
||||
is_forbid_parallel = false;
|
||||
const uint64_t tenant_id = get_tenant_id();
|
||||
for (int i = 0; OB_SUCC(ret) && !is_forbid_parallel && i < trigger_list_.count(); i++) {
|
||||
OZ (schema_guard.get_trigger_info(tenant_id, trigger_list_.at(i), trigger_info), trigger_list_.at(i));
|
||||
OV (OB_NOT_NULL(trigger_info), OB_ERR_UNEXPECTED, trigger_list_.at(i));
|
||||
OX (is_forbid_parallel = trigger_info->is_reads_sql_data() ||
|
||||
trigger_info->is_modifies_sql_data() ||
|
||||
trigger_info->is_wps() ||
|
||||
trigger_info->is_rps() ||
|
||||
trigger_info->is_has_sequence() ||
|
||||
trigger_info->is_external_state());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const ObColumnSchemaV2 *ObColumnIterByPrevNextID::get_first_column() const
|
||||
{
|
||||
ObColumnSchemaV2 *ret_col = NULL;
|
||||
|
@ -1284,6 +1284,8 @@ public:
|
||||
bool &trigger_exist) const;
|
||||
int has_before_update_row_trigger(ObSchemaGetterGuard &schema_guard,
|
||||
bool &trigger_exist) const;
|
||||
int is_allow_parallel_of_trigger(ObSchemaGetterGuard &schema_guard,
|
||||
bool &is_forbid_parallel) const;
|
||||
|
||||
//label security
|
||||
inline bool has_label_se_column() const { return label_se_column_ids_.count() > 0; }
|
||||
|
@ -53,7 +53,8 @@ OB_SERIALIZE_MEMBER((ObTriggerInfo, ObSimpleTriggerSchema),
|
||||
order_type_,
|
||||
ref_trg_db_name_,
|
||||
ref_trg_name_,
|
||||
action_order_);
|
||||
action_order_,
|
||||
analyze_flag_);
|
||||
|
||||
ObTriggerInfo &ObTriggerInfo::operator =(const ObTriggerInfo &other)
|
||||
{
|
||||
@ -103,6 +104,7 @@ void ObTriggerInfo::reset()
|
||||
reset_string(ref_trg_name_);
|
||||
action_order_ = 0;
|
||||
ObSimpleTriggerSchema::reset();
|
||||
analyze_flag_ = 0;
|
||||
}
|
||||
|
||||
bool ObTriggerInfo::is_valid_for_create() const
|
||||
@ -164,6 +166,7 @@ int ObTriggerInfo::deep_copy(const ObTriggerInfo &other)
|
||||
OZ (set_ref_trg_db_name(other.get_ref_trg_db_name()));
|
||||
OZ (set_ref_trg_name(other.get_ref_trg_name()));
|
||||
OX (set_action_order(other.get_action_order()));
|
||||
OX (set_analyze_flag(other.get_analyze_flag()));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -408,6 +408,29 @@ public:
|
||||
OB_INLINE const common::ObString &get_ref_trg_db_name() const { return ref_trg_db_name_; }
|
||||
OB_INLINE const common::ObString &get_ref_trg_name() const { return ref_trg_name_; }
|
||||
OB_INLINE int64_t get_action_order() const { return action_order_; }
|
||||
|
||||
OB_INLINE void set_analyze_flag(uint64_t flag) { analyze_flag_ = flag; }
|
||||
OB_INLINE uint64_t get_analyze_flag() const { return analyze_flag_; }
|
||||
|
||||
OB_INLINE void set_no_sql() { is_no_sql_ = true; is_reads_sql_data_ = false; is_modifies_sql_data_ = false; is_contains_sql_ = false; }
|
||||
OB_INLINE bool is_no_sql() const { return is_no_sql_; }
|
||||
OB_INLINE void set_reads_sql_data() { is_no_sql_ = false; is_reads_sql_data_ = true; is_modifies_sql_data_ = false; is_contains_sql_ = false; }
|
||||
OB_INLINE bool is_reads_sql_data() const { return is_reads_sql_data_; }
|
||||
OB_INLINE void set_modifies_sql_data() { is_no_sql_ = false; is_reads_sql_data_ = false; is_modifies_sql_data_ = true; is_contains_sql_ = false; }
|
||||
OB_INLINE bool is_modifies_sql_data() const { return is_modifies_sql_data_; }
|
||||
OB_INLINE void set_contains_sql() { is_no_sql_ = false; is_reads_sql_data_ = false; is_modifies_sql_data_ = false; is_contains_sql_ = true; }
|
||||
OB_INLINE bool is_contains_sql() const { return is_contains_sql_; }
|
||||
|
||||
OB_INLINE void set_wps(bool v) { is_wps_ = v; }
|
||||
OB_INLINE bool is_wps() const { return is_wps_; }
|
||||
OB_INLINE void set_rps(bool v) { is_rps_ = v; }
|
||||
OB_INLINE bool is_rps() const { return is_rps_; }
|
||||
OB_INLINE void set_has_sequence(bool v) { is_has_sequence_ = v; }
|
||||
OB_INLINE bool is_has_sequence() const { return is_has_sequence_; }
|
||||
OB_INLINE void set_has_out_param(bool v) { is_has_out_param_ = v; }
|
||||
OB_INLINE bool is_has_out_param() const { return is_has_out_param_; }
|
||||
OB_INLINE void set_external_state(bool v) { is_external_state_ = v; }
|
||||
OB_INLINE bool is_external_state() const { return is_external_state_; }
|
||||
OB_INLINE bool is_row_level_before_trigger() const { return is_simple_dml_type() && timing_points_.only_before_row(); }
|
||||
OB_INLINE bool is_row_level_after_trigger() const { return is_simple_dml_type() && timing_points_.only_after_row(); }
|
||||
OB_INLINE bool is_stmt_level_before_trigger() const { return is_simple_dml_type() && timing_points_.only_before_stmt(); }
|
||||
@ -508,7 +531,8 @@ public:
|
||||
K(order_type_),
|
||||
K(ref_trg_db_name_),
|
||||
K(ref_trg_name_),
|
||||
K(action_order_));
|
||||
K(action_order_),
|
||||
K(analyze_flag_));
|
||||
protected:
|
||||
static int gen_package_source_simple(const ObTriggerInfo &trigger_info,
|
||||
const common::ObString &base_object_database,
|
||||
@ -595,6 +619,21 @@ protected:
|
||||
common::ObString ref_trg_db_name_; // 排序方式中指定的trigger的db name
|
||||
common::ObString ref_trg_name_; // 排序方式中指定的trigger的name
|
||||
int64_t action_order_; // 该值在rs端计算,从系统表里面读出来的值是有意义的
|
||||
union {
|
||||
uint64_t analyze_flag_;
|
||||
struct {
|
||||
uint64_t is_no_sql_ : 1;
|
||||
uint64_t is_reads_sql_data_ : 1;
|
||||
uint64_t is_modifies_sql_data_ : 1;
|
||||
uint64_t is_contains_sql_ : 1;
|
||||
uint64_t is_wps_ : 1;
|
||||
uint64_t is_rps_ : 1;
|
||||
uint64_t is_has_sequence_ : 1;
|
||||
uint64_t is_has_out_param_ : 1;
|
||||
uint64_t is_external_state_ : 1;
|
||||
uint64_t reserved_:54;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
@ -264,6 +264,18 @@ int ObTriggerSqlService::fill_dml_sql(const ObTriggerInfo &trigger_info,
|
||||
OZ (dml.add_column("ref_trg_db_name", ObHexEscapeSqlStr(trigger_info.get_ref_trg_db_name())));
|
||||
OZ (dml.add_column("ref_trg_name", ObHexEscapeSqlStr(trigger_info.get_ref_trg_name())));
|
||||
OZ (dml.add_column("action_order", trigger_info.get_action_order()));
|
||||
if (OB_SUCC(ret)) {
|
||||
uint64_t data_version = 0;
|
||||
if (OB_FAIL(GET_MIN_DATA_VERSION(trigger_info.get_tenant_id(), data_version))) {
|
||||
LOG_WARN("failed to get data version", K(ret));
|
||||
} else if (data_version < DATA_VERSION_4_2_0_0 && 0 != trigger_info.get_analyze_flag()) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_WARN("tenant data version is less than 4.2, analyze_flag column is not supported", K(ret), K(data_version));
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "tenant data version is less than 4.2, analyze_flag column");
|
||||
} else if (data_version >= DATA_VERSION_4_2_0_0) {
|
||||
OZ (dml.add_column("analyze_flag", trigger_info.get_analyze_flag()));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1690,6 +1690,7 @@ int ObDmlCgService::add_trigger_arg(const ObTriggerInfo &trigger_info, ObDMLBase
|
||||
trigger_arg.set_trigger_id(trigger_info.get_trigger_id());
|
||||
trigger_arg.set_trigger_events(trigger_info.get_trigger_events());
|
||||
trigger_arg.set_timing_points(trigger_info.get_timing_points());
|
||||
trigger_arg.set_analyze_flag(trigger_info.get_analyze_flag());
|
||||
if (OB_FAIL(dml_ctdef.trig_ctdef_.tg_args_.push_back(trigger_arg))) {
|
||||
LOG_WARN("failed to add trigger arg", K(ret));
|
||||
} else {
|
||||
@ -2077,10 +2078,27 @@ int ObDmlCgService::convert_normal_triggers(ObLogDelUpd &log_op,
|
||||
}
|
||||
LOG_DEBUG("debug trigger", K(trig_ctdef.new_row_exprs_.count()),
|
||||
K(trig_ctdef.old_row_exprs_.count()));
|
||||
cg_.phy_plan_->set_has_nested_sql(true);
|
||||
//为了支持触发器/UDF支持异常捕获,要求含有trigger的涉及修改表数据的dml串行执行
|
||||
cg_.phy_plan_->set_need_serial_exec(true);
|
||||
cg_.phy_plan_->set_contain_pl_udf_or_trigger(true);
|
||||
bool is_forbid_parallel = false;
|
||||
const ObTriggerInfo *trigger_info = NULL;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && !is_forbid_parallel && i < trigger_infos.count(); ++i) {
|
||||
trigger_info = trigger_infos.at(i);
|
||||
if (trigger_info->is_modifies_sql_data() ||
|
||||
trigger_info->is_wps() ||
|
||||
trigger_info->is_rps() ||
|
||||
trigger_info->is_has_sequence()) {
|
||||
is_forbid_parallel = true;
|
||||
} else if (trigger_info->is_reads_sql_data()) { // dml + trigger(select) serial execute
|
||||
is_forbid_parallel = true;
|
||||
} else if (trigger_info->is_external_state()) {
|
||||
is_forbid_parallel = true;
|
||||
}
|
||||
}
|
||||
if (is_forbid_parallel) {
|
||||
cg_.phy_plan_->set_has_nested_sql(true);
|
||||
//为了支持触发器/UDF支持异常捕获,要求含有trigger的涉及修改表数据的dml串行执行
|
||||
cg_.phy_plan_->set_need_serial_exec(true);
|
||||
cg_.phy_plan_->set_contain_pl_udf_or_trigger(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -6575,7 +6575,7 @@ int ObStaticEngineCG::set_other_properties(const ObLogPlan &log_plan, ObPhysical
|
||||
if (OB_ISNULL(log_plan.get_stmt())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (log_plan.get_stmt()->get_query_ctx()->has_pl_udf_) {
|
||||
} else if (log_plan.get_stmt()->get_query_ctx()->disable_udf_parallel_) {
|
||||
if (log_plan.get_stmt()->is_insert_stmt() ||
|
||||
log_plan.get_stmt()->is_update_stmt() ||
|
||||
log_plan.get_stmt()->is_delete_stmt() ||
|
||||
|
@ -68,6 +68,7 @@ int ObCallProcedureExecutor::execute(ObExecContext &ctx, ObCallProcedureStmt &st
|
||||
int ret = OB_SUCCESS;
|
||||
uint64_t package_id = OB_INVALID_ID;
|
||||
uint64_t routine_id = OB_INVALID_ID;
|
||||
ObCallProcedureInfo *call_proc_info = NULL;
|
||||
LOG_DEBUG("call procedure execute", K(stmt));
|
||||
if (OB_ISNULL(ctx.get_pl_engine()) || OB_ISNULL(ctx.get_output_row())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
@ -89,27 +90,42 @@ int ObCallProcedureExecutor::execute(ObExecContext &ctx, ObCallProcedureStmt &st
|
||||
ctx.get_my_session()->get_current_query_string(),
|
||||
ctx.get_stmt_factory()->get_query_ctx()->get_sql_stmt()))) {
|
||||
LOG_WARN("fail to set query string");
|
||||
} else if (OB_ISNULL(call_proc_info = stmt.get_call_proc_info())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("call procedure info is null", K(ret));
|
||||
} else {
|
||||
ParamStore params( (ObWrapperAllocator(ctx.get_allocator())) );
|
||||
const share::schema::ObRoutineInfo *routine_info = NULL;
|
||||
|
||||
if (!stmt.can_direct_use_param()) {
|
||||
if (!call_proc_info->can_direct_use_param()) {
|
||||
ObObjParam param;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < stmt.get_params().count(); ++i) {
|
||||
const ObRawExpr *expr = stmt.get_params().at(i);
|
||||
const ParamStore &origin_params = ctx.get_physical_plan_ctx()->get_param_store_for_update();
|
||||
pl::ExecCtxBak exec_ctx_bak;
|
||||
sql::ObPhysicalPlanCtx phy_plan_ctx(ctx.get_allocator());
|
||||
phy_plan_ctx.set_timeout_timestamp(ctx.get_physical_plan_ctx()->get_timeout_timestamp());
|
||||
exec_ctx_bak.backup(ctx);
|
||||
ctx.set_physical_plan_ctx(&phy_plan_ctx);
|
||||
if (call_proc_info->get_expr_op_size() > 0) {
|
||||
OZ (ctx.init_expr_op(call_proc_info->get_expr_op_size()));
|
||||
}
|
||||
OZ (call_proc_info->get_frame_info().pre_alloc_exec_memory(ctx));
|
||||
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < origin_params.count(); ++i) {
|
||||
OZ (phy_plan_ctx.get_param_store_for_update().push_back(origin_params.at(i)));
|
||||
}
|
||||
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < call_proc_info->get_expressions().count(); ++i) {
|
||||
const ObSqlExpression *expr = call_proc_info->get_expressions().at(i);
|
||||
if (OB_ISNULL(expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("param expr NULL", K(i), K(ret));
|
||||
} else {
|
||||
param.reset();
|
||||
param.ObObj::reset();
|
||||
param.set_accuracy(expr->get_accuracy());
|
||||
param.set_result_flag(expr->get_result_flag());
|
||||
if (OB_FAIL(ObSQLUtils::calc_raw_expr_without_row(ctx, expr, param,
|
||||
&(ctx.get_physical_plan_ctx()->get_param_store_for_update()), ctx.get_allocator()))) {
|
||||
if (OB_FAIL(ObSQLUtils::calc_sql_expression_without_row(ctx, *expr, param))) {
|
||||
LOG_WARN("failed to calc exec param expr", K(i), K(*expr), K(ret));
|
||||
} else {
|
||||
if (expr->has_flag(ObExprInfoFlag::IS_PL_MOCK_DEFAULT_EXPR)) {
|
||||
if (expr->get_is_pl_mock_default_expr()) {
|
||||
param.set_is_pl_mock_default_param(true);
|
||||
}
|
||||
if (OB_FAIL(params.push_back(param))) {
|
||||
@ -120,12 +136,18 @@ int ObCallProcedureExecutor::execute(ObExecContext &ctx, ObCallProcedureStmt &st
|
||||
}
|
||||
}
|
||||
} // for end
|
||||
|
||||
if (call_proc_info->get_expr_op_size() > 0) {
|
||||
ctx.reset_expr_op();
|
||||
ctx.get_allocator().free(ctx.get_expr_op_ctx_store());
|
||||
}
|
||||
exec_ctx_bak.restore(ctx);
|
||||
} else {
|
||||
LOG_DEBUG("direct use params", K(ret), K(stmt));
|
||||
int64_t param_cnt = ctx.get_physical_plan_ctx()->get_param_store().count();
|
||||
if (stmt.get_param_cnt() != param_cnt) {
|
||||
if (call_proc_info->get_param_cnt() != param_cnt) {
|
||||
ret = OB_ERR_SP_WRONG_ARG_NUM;
|
||||
LOG_WARN("argument number not equal", K(stmt.get_param_cnt()), K(param_cnt), K(ret));
|
||||
LOG_WARN("argument number not equal", K(call_proc_info->get_param_cnt()), K(param_cnt), K(ret));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < param_cnt; ++i) {
|
||||
LOG_DEBUG("params", "param", ctx.get_physical_plan_ctx()->get_param_store().at(i), K(i));
|
||||
@ -135,14 +157,14 @@ int ObCallProcedureExecutor::execute(ObExecContext &ctx, ObCallProcedureStmt &st
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
package_id = stmt.get_package_id();
|
||||
routine_id = stmt.get_routine_id();
|
||||
package_id = call_proc_info->get_package_id();
|
||||
routine_id = call_proc_info->get_routine_id();
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ObArray<int64_t> path;
|
||||
ObArray<int64_t> nocopy_params;
|
||||
ObObj result;
|
||||
int64_t pkg_id = stmt.is_udt_routine()
|
||||
int64_t pkg_id = call_proc_info->is_udt_routine()
|
||||
? share::schema::ObUDTObjectType::mask_object_id(package_id) : package_id;
|
||||
if (OB_FAIL(ctx.get_pl_engine()->execute(ctx,
|
||||
ctx.get_allocator(),
|
||||
@ -160,20 +182,20 @@ int ObCallProcedureExecutor::execute(ObExecContext &ctx, ObCallProcedureStmt &st
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (stmt.get_output_count() > 0) {
|
||||
ctx.get_output_row()->count_ = stmt.get_output_count();
|
||||
} else if (call_proc_info->get_output_count() > 0) {
|
||||
ctx.get_output_row()->count_ = call_proc_info->get_output_count();
|
||||
if (OB_ISNULL(ctx.get_output_row()->cells_ = static_cast<ObObj *>(
|
||||
ctx.get_allocator().alloc(sizeof(ObObj) * stmt.get_output_count())))) {
|
||||
ctx.get_allocator().alloc(sizeof(ObObj) * call_proc_info->get_output_count())))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_WARN("fail to alloc obj array", K(stmt.get_output_count()), K(ret));
|
||||
LOG_WARN("fail to alloc obj array", K(call_proc_info->get_output_count()), K(ret));
|
||||
} else {
|
||||
int64_t idx = 0;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < params.count(); ++i) {
|
||||
if (stmt.is_out_param(i)) {
|
||||
if (call_proc_info->is_out_param(i)) {
|
||||
if (ob_is_enum_or_set_type(params.at(i).get_type())) {
|
||||
OZ (ObSPIService::cast_enum_set_to_string(
|
||||
ctx,
|
||||
stmt.get_out_type().at(idx).get_type_info(),
|
||||
call_proc_info->get_out_type().at(idx).get_type_info(),
|
||||
params.at(i),
|
||||
ctx.get_output_row()->cells_[idx]));
|
||||
OX (idx++);
|
||||
@ -183,30 +205,26 @@ int ObCallProcedureExecutor::execute(ObExecContext &ctx, ObCallProcedureStmt &st
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (!stmt.can_direct_use_param()) {
|
||||
const ObRawExpr *expr = stmt.get_params().at(i);
|
||||
if (OB_LIKELY(expr->is_const_raw_expr())) {
|
||||
const ObConstRawExpr *const_expr = static_cast<const ObConstRawExpr *>(expr);
|
||||
if (T_QUESTIONMARK == const_expr->get_expr_type()) {
|
||||
int64_t idx = const_expr->get_value().get_unknown();
|
||||
} else if (!call_proc_info->can_direct_use_param()) {
|
||||
const ObSqlExpression *expr = call_proc_info->get_expressions().at(i);
|
||||
ObItemType expr_type = expr->get_expr_items().at(0).get_item_type();
|
||||
if (OB_LIKELY(IS_CONST_TYPE(expr_type))) {
|
||||
const ObObj &value = expr->get_expr_items().at(0).get_obj();
|
||||
if (T_QUESTIONMARK == expr_type) {
|
||||
int64_t idx = value.get_unknown();
|
||||
ctx.get_physical_plan_ctx()->get_param_store_for_update().at(idx) = params.at(i);
|
||||
} else {
|
||||
/* do nothing */
|
||||
}
|
||||
} else if (T_OP_GET_USER_VAR == expr->get_expr_type()) { //这里只有可能出现用户变量
|
||||
const ObSysFunRawExpr *func_expr = static_cast<const ObSysFunRawExpr*>(expr);
|
||||
} else if (T_OP_GET_USER_VAR == expr_type) { //这里只有可能出现用户变量
|
||||
ObExprCtx expr_ctx;
|
||||
if (OB_FAIL(ObSQLUtils::wrap_expr_ctx(stmt.get_stmt_type(), ctx, ctx.get_allocator(), expr_ctx))) {
|
||||
if (expr->get_expr_items().count() < 2 || T_VARCHAR != expr->get_expr_items().at(1).get_item_type()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("Unexpected result expr", K(*expr), K(ret));
|
||||
} else if (OB_FAIL(ObSQLUtils::wrap_expr_ctx(stmt.get_stmt_type(), ctx, ctx.get_allocator(), expr_ctx))) {
|
||||
LOG_WARN("Failed to wrap expr ctx", K(ret));
|
||||
} else if (OB_ISNULL(func_expr->get_param_expr(0))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("sys var is NULL", K(*func_expr), K(ret));
|
||||
} else if (OB_UNLIKELY(!func_expr->get_param_expr(0)->is_const_raw_expr()
|
||||
|| !static_cast<const ObConstRawExpr*>(func_expr->get_param_expr(0))->get_value().is_varchar())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("invalid sys var", K(*func_expr->get_param_expr(0)), K(ret));
|
||||
} else {
|
||||
const ObString var_name = static_cast<const ObConstRawExpr*>(func_expr->get_param_expr(0))->get_value().get_varchar();
|
||||
const ObString var_name = expr->get_expr_items().at(1).get_obj().get_string();
|
||||
if (OB_FAIL(ObVariableSetExecutor::set_user_variable(params.at(i), var_name, expr_ctx))) {
|
||||
LOG_WARN("set user variable failed", K(ret));
|
||||
}
|
||||
|
@ -59,10 +59,7 @@ int ObCreateTriggerExecutor::execute(ObExecContext &ctx, ObCreateTriggerStmt &st
|
||||
ctx.get_allocator(),
|
||||
arg));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (lib::is_oracle_mode() ||
|
||||
(lib::is_mysql_mode() && arg.error_info_.get_error_status() != ERROR_STATUS_NO_ERROR)) {
|
||||
OZ (common_rpc_proxy->create_trigger(arg), common_rpc_proxy->get_server());
|
||||
}
|
||||
OZ (common_rpc_proxy->create_trigger(arg), common_rpc_proxy->get_server());
|
||||
}
|
||||
OZ (ctx.get_sql_ctx()->schema_guard_->reset());
|
||||
return ret;
|
||||
@ -134,7 +131,8 @@ int ObCreateTriggerExecutor::analyze_dependencies(ObSchemaGetterGuard &schema_gu
|
||||
if (OB_SUCC(ret)) {
|
||||
arg.trigger_info_.deep_copy(*trigger_info);
|
||||
arg.error_info_.collect_error_info(&arg.trigger_info_);
|
||||
arg.for_insert_errors_ = true;
|
||||
arg.in_second_stage_ = true;
|
||||
arg.with_replace_ = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -153,7 +153,8 @@ public:
|
||||
ObTriggerArg()
|
||||
: trigger_id_(common::OB_INVALID_ID),
|
||||
trigger_events_(),
|
||||
timing_points_()
|
||||
timing_points_(),
|
||||
analyze_flag_(0)
|
||||
{}
|
||||
inline void reset()
|
||||
{
|
||||
@ -174,6 +175,23 @@ public:
|
||||
{
|
||||
timing_points_.set_value(timing_points);
|
||||
}
|
||||
inline void set_analyze_flag(uint64_t flag) { analyze_flag_ = flag; }
|
||||
|
||||
inline bool is_no_sql() const { return is_no_sql_; }
|
||||
inline bool is_reads_sql_data() const { return is_reads_sql_data_; }
|
||||
inline bool is_modifies_sql_data() const { return is_modifies_sql_data_; }
|
||||
inline bool is_contains_sql() const { return is_contains_sql_; }
|
||||
inline bool is_wps() const { return is_wps_; }
|
||||
inline bool is_rps() const { return is_rps_; }
|
||||
inline bool is_has_sequence() const { return is_has_sequence_; }
|
||||
inline bool is_has_out_param() const { return is_has_out_param_; }
|
||||
inline bool is_external_state() const { return is_external_state_; }
|
||||
|
||||
inline bool is_execute_single_row() const
|
||||
{
|
||||
return (is_modifies_sql_data_ || is_wps_ || is_rps_ || is_has_sequence_ ||
|
||||
is_reads_sql_data_ || is_external_state_);
|
||||
}
|
||||
|
||||
inline uint64_t get_trigger_id() const { return trigger_id_; }
|
||||
inline bool has_when_condition() const { return timing_points_.has_when_condition(); }
|
||||
@ -198,6 +216,21 @@ private:
|
||||
share::schema::ObTimingPoints timing_points_;
|
||||
common::ObString package_spec_;
|
||||
common::ObString package_body_;
|
||||
union {
|
||||
uint64_t analyze_flag_;
|
||||
struct {
|
||||
uint64_t is_no_sql_ : 1; // it marks trigger do not contain sql stmt
|
||||
uint64_t is_reads_sql_data_ : 1; // it marks trigger contain read sql stmt, such as select stmt
|
||||
uint64_t is_modifies_sql_data_ : 1; // it marks trigger contain write sql stmt
|
||||
uint64_t is_contains_sql_ : 1; // it marks trigger do not contain read and write sql, but contain other sql stmt, such as set stmt
|
||||
uint64_t is_wps_ : 1; // it marks trigger write package var
|
||||
uint64_t is_rps_ : 1; // it marks trigger read package var
|
||||
uint64_t is_has_sequence_ : 1; // it marks trigger used sequence
|
||||
uint64_t is_has_out_param_ : 1; // it marks trigger has out param
|
||||
uint64_t is_external_state_ : 1; // it marks trigger access other store routine or global var etc..
|
||||
uint64_t reserved_:54;
|
||||
};
|
||||
};
|
||||
};
|
||||
typedef common::ObFixedArray<ObTriggerArg, common::ObIAllocator> ObTriggerArgArray;
|
||||
|
||||
|
@ -142,8 +142,11 @@ int ObTableDeleteOp::check_need_exec_single_row()
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < MY_SPEC.del_ctdefs_.count() && !execute_single_row_; ++i) {
|
||||
const ObTableDeleteSpec::DelCtDefArray &ctdefs = MY_SPEC.del_ctdefs_.at(i);
|
||||
const ObDelCtDef &del_ctdef = *ctdefs.at(0);
|
||||
if (has_before_row_trigger(del_ctdef) || has_after_row_trigger(del_ctdef)) {
|
||||
execute_single_row_ = true;
|
||||
for (int64_t j = 0;
|
||||
OB_SUCC(ret) && !execute_single_row_ && j < del_ctdef.trig_ctdef_.tg_args_.count();
|
||||
++j) {
|
||||
const ObTriggerArg &tri_arg = del_ctdef.trig_ctdef_.tg_args_.at(j);
|
||||
execute_single_row_ = tri_arg.is_execute_single_row();
|
||||
}
|
||||
const ObForeignKeyArgArray &fk_args = del_ctdef.fk_args_;
|
||||
for (int j = 0; OB_SUCC(ret) && j < fk_args.count() && !execute_single_row_; j++) {
|
||||
|
@ -111,8 +111,11 @@ int ObTableInsertAllOp::check_need_exec_single_row()
|
||||
const ObInsCtDef &ins_ctdef = *(ctdefs.at(0));
|
||||
const uint64_t table_id = ins_ctdef.das_base_ctdef_.index_tid_;
|
||||
const ObForeignKeyArgArray &fk_args = ins_ctdef.fk_args_;
|
||||
if (has_before_row_trigger(ins_ctdef) || has_after_row_trigger(ins_ctdef)) {
|
||||
execute_single_row_ = true;
|
||||
for (int64_t j = 0;
|
||||
OB_SUCC(ret) && !execute_single_row_ && j < ins_ctdef.trig_ctdef_.tg_args_.count();
|
||||
++j) {
|
||||
const ObTriggerArg &tri_arg = ins_ctdef.trig_ctdef_.tg_args_.at(j);
|
||||
execute_single_row_ = tri_arg.is_execute_single_row();
|
||||
}
|
||||
for (int j = 0; OB_SUCC(ret) && j < fk_args.count() && !execute_single_row_; j++) {
|
||||
const ObForeignKeyArg &fk_arg = fk_args.at(j);
|
||||
|
@ -116,8 +116,11 @@ int ObTableInsertOp::check_need_exec_single_row()
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < MY_SPEC.ins_ctdefs_.count() && !execute_single_row_; ++i) {
|
||||
const ObTableInsertSpec::InsCtDefArray &ctdefs = MY_SPEC.ins_ctdefs_.at(i);
|
||||
const ObInsCtDef &ins_ctdef = *ctdefs.at(0);
|
||||
if (has_before_row_trigger(ins_ctdef) || has_after_row_trigger(ins_ctdef)) {
|
||||
execute_single_row_ = true;
|
||||
for (int64_t j = 0;
|
||||
OB_SUCC(ret) && !execute_single_row_ && j < ins_ctdef.trig_ctdef_.tg_args_.count();
|
||||
++j) {
|
||||
const ObTriggerArg &tri_arg = ins_ctdef.trig_ctdef_.tg_args_.at(j);
|
||||
execute_single_row_ = tri_arg.is_execute_single_row();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,9 +97,17 @@ int ObTableInsertUpOp::check_need_exec_single_row()
|
||||
const ObInsCtDef *ins_ctdef = insert_up_ctdef->ins_ctdef_;
|
||||
const ObUpdCtDef *upd_ctdef = insert_up_ctdef->upd_ctdef_;
|
||||
if (OB_NOT_NULL(ins_ctdef) && OB_NOT_NULL(upd_ctdef)) {
|
||||
if (has_before_row_trigger(*ins_ctdef) || has_after_row_trigger(*ins_ctdef) ||
|
||||
has_before_row_trigger(*upd_ctdef) || has_after_row_trigger(*upd_ctdef)) {
|
||||
execute_single_row_ = true;
|
||||
for (int64_t j = 0;
|
||||
OB_SUCC(ret) && !execute_single_row_ && j < ins_ctdef->trig_ctdef_.tg_args_.count();
|
||||
++j) {
|
||||
const ObTriggerArg &tri_arg = ins_ctdef->trig_ctdef_.tg_args_.at(j);
|
||||
execute_single_row_ = tri_arg.is_execute_single_row();
|
||||
}
|
||||
for (int64_t j = 0;
|
||||
OB_SUCC(ret) && !execute_single_row_ && j < upd_ctdef->trig_ctdef_.tg_args_.count();
|
||||
++j) {
|
||||
const ObTriggerArg &tri_arg = upd_ctdef->trig_ctdef_.tg_args_.at(j);
|
||||
execute_single_row_ = tri_arg.is_execute_single_row();
|
||||
}
|
||||
} else {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
|
@ -161,22 +161,31 @@ int ObTableMergeOp::check_need_exec_single_row()
|
||||
ObMergeCtDef *merge_ctdef = MY_SPEC.merge_ctdefs_.at(0);
|
||||
if (!execute_single_row_ && OB_NOT_NULL(merge_ctdef->ins_ctdef_)) {
|
||||
const ObInsCtDef &ins_ctdef = *merge_ctdef->ins_ctdef_;
|
||||
if (has_before_row_trigger(ins_ctdef) || has_after_row_trigger(ins_ctdef)) {
|
||||
execute_single_row_ = true;
|
||||
for (int64_t j = 0;
|
||||
OB_SUCC(ret) && !execute_single_row_ && j < ins_ctdef.trig_ctdef_.tg_args_.count();
|
||||
++j) {
|
||||
const ObTriggerArg &tri_arg = ins_ctdef.trig_ctdef_.tg_args_.at(j);
|
||||
execute_single_row_ = tri_arg.is_execute_single_row();
|
||||
}
|
||||
}
|
||||
|
||||
if (!execute_single_row_ && OB_NOT_NULL(merge_ctdef->upd_ctdef_)) {
|
||||
const ObUpdCtDef &upd_ctdef = *merge_ctdef->upd_ctdef_;
|
||||
if (has_before_row_trigger(upd_ctdef) || has_after_row_trigger(upd_ctdef)) {
|
||||
execute_single_row_ = true;
|
||||
for (int64_t j = 0;
|
||||
OB_SUCC(ret) && !execute_single_row_ && j < upd_ctdef.trig_ctdef_.tg_args_.count();
|
||||
++j) {
|
||||
const ObTriggerArg &tri_arg = upd_ctdef.trig_ctdef_.tg_args_.at(j);
|
||||
execute_single_row_ = tri_arg.is_execute_single_row();
|
||||
}
|
||||
}
|
||||
|
||||
if (!execute_single_row_ && OB_NOT_NULL(merge_ctdef->del_ctdef_)) {
|
||||
const ObDelCtDef &del_ctdef = *merge_ctdef->del_ctdef_;
|
||||
if (has_before_row_trigger(del_ctdef) || has_after_row_trigger(del_ctdef)) {
|
||||
execute_single_row_ = true;
|
||||
for (int64_t j = 0;
|
||||
OB_SUCC(ret) && !execute_single_row_ && j < del_ctdef.trig_ctdef_.tg_args_.count();
|
||||
++j) {
|
||||
const ObTriggerArg &tri_arg = del_ctdef.trig_ctdef_.tg_args_.at(j);
|
||||
execute_single_row_ = tri_arg.is_execute_single_row();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,10 +102,20 @@ int ObTableReplaceOp::check_need_exec_single_row()
|
||||
ObReplaceCtDef *replace_ctdef = MY_SPEC.replace_ctdefs_.at(0);
|
||||
const ObInsCtDef *ins_ctdef = replace_ctdef->ins_ctdef_;
|
||||
const ObDelCtDef *del_ctdef = replace_ctdef->del_ctdef_;
|
||||
if (OB_NOT_NULL(ins_ctdef) || OB_NOT_NULL(del_ctdef)) {
|
||||
if (has_before_row_trigger(*ins_ctdef) || has_after_row_trigger(*ins_ctdef)
|
||||
|| has_before_row_trigger(*del_ctdef) || has_after_row_trigger(*del_ctdef)) {
|
||||
execute_single_row_ = true;
|
||||
if (OB_NOT_NULL(ins_ctdef)) {
|
||||
for (int64_t j = 0;
|
||||
OB_SUCC(ret) && !execute_single_row_ && j < ins_ctdef->trig_ctdef_.tg_args_.count();
|
||||
++j) {
|
||||
const ObTriggerArg &tri_arg = ins_ctdef->trig_ctdef_.tg_args_.at(j);
|
||||
execute_single_row_ = tri_arg.is_execute_single_row();
|
||||
}
|
||||
}
|
||||
if (OB_NOT_NULL(del_ctdef)) {
|
||||
for (int64_t j = 0;
|
||||
OB_SUCC(ret) && !execute_single_row_ && j < del_ctdef->trig_ctdef_.tg_args_.count();
|
||||
++j) {
|
||||
const ObTriggerArg &tri_arg = del_ctdef->trig_ctdef_.tg_args_.at(j);
|
||||
execute_single_row_ = tri_arg.is_execute_single_row();
|
||||
}
|
||||
} else {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
|
@ -121,8 +121,11 @@ int ObTableUpdateOp::check_need_exec_single_row()
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < MY_SPEC.upd_ctdefs_.count() && !execute_single_row_; ++i) {
|
||||
const ObTableUpdateSpec::UpdCtDefArray &ctdefs = MY_SPEC.upd_ctdefs_.at(i);
|
||||
const ObUpdCtDef &upd_ctdef = *ctdefs.at(0);
|
||||
if (has_before_row_trigger(upd_ctdef) || has_after_row_trigger(upd_ctdef)) {
|
||||
execute_single_row_ = true;
|
||||
for (int64_t j = 0;
|
||||
OB_SUCC(ret) && !execute_single_row_ && j < upd_ctdef.trig_ctdef_.tg_args_.count();
|
||||
++j) {
|
||||
const ObTriggerArg &tri_arg = upd_ctdef.trig_ctdef_.tg_args_.at(j);
|
||||
execute_single_row_ = tri_arg.is_execute_single_row();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -406,6 +406,8 @@ int TriggerHandle::calc_trigger_routine(
|
||||
OZ (exec_ctx.get_pl_engine()->execute(
|
||||
exec_ctx, exec_ctx.get_allocator(), trigger_id, routine_id, path, params, nocopy_params, result),
|
||||
trigger_id, routine_id, params);
|
||||
CK (OB_NOT_NULL(exec_ctx.get_my_session()));
|
||||
OZ (exec_ctx.get_my_session()->reset_all_package_state_by_dbms_session(true));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -882,6 +882,15 @@ int ObResultSet::close()
|
||||
}
|
||||
ret = auto_end_plan_trans(*physical_plan_, ret, async);
|
||||
}
|
||||
|
||||
if (is_user_sql_ && my_session_.need_reset_package()) {
|
||||
// need_reset_package is set, it must be reset package, wether exec succ or not.
|
||||
int tmp_ret = my_session_.reset_all_package_state_by_dbms_session(true);
|
||||
if (OB_SUCCESS != tmp_ret) {
|
||||
LOG_WARN("reset all package fail. ", K(tmp_ret), K(ret));
|
||||
ret = OB_SUCCESS == ret ? tmp_ret : ret;
|
||||
}
|
||||
}
|
||||
//NG_TRACE_EXT(result_set_close, OB_ID(ret), ret, OB_ID(arg1), prev_ret,
|
||||
//OB_ID(arg2), ins_ret, OB_ID(arg3), errcode_, OB_ID(async), async);
|
||||
return ret; // 后面所有的操作都通过callback来完成
|
||||
@ -1160,22 +1169,6 @@ bool ObResultSet::need_end_trans_callback() const
|
||||
return need;
|
||||
}
|
||||
|
||||
static int check_is_pl_jsontype(const oceanbase::pl::ObUserDefinedType *user_type)
|
||||
{
|
||||
INIT_SUCC(ret);
|
||||
|
||||
if (OB_ISNULL(user_type)) {
|
||||
} else if (user_type->get_type() == oceanbase::pl::PL_OPAQUE_TYPE) {
|
||||
if (user_type->get_name().compare("JSON_OBJECT_T") == 0
|
||||
|| user_type->get_name().compare("JSON_ELEMENT_T") == 0) {
|
||||
ret = OB_ERR_PL_JSONTYPE_USAGE;
|
||||
LOG_WARN("invalid pl json type userage in pl/sql", K(ret),
|
||||
K(user_type->get_type()), K(user_type->get_user_type_id()));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObResultSet::ExternalRetrieveInfo::build_into_exprs(
|
||||
ObStmt &stmt, pl::ObPLBlockNS *ns, bool is_dynamic_sql)
|
||||
{
|
||||
@ -1187,56 +1180,13 @@ int ObResultSet::ExternalRetrieveInfo::build_into_exprs(
|
||||
}
|
||||
is_select_for_update_ = (static_cast<ObSelectStmt&>(stmt)).has_for_update();
|
||||
has_hidden_rowid_ = (static_cast<ObSelectStmt&>(stmt)).has_hidden_rowid();
|
||||
is_bulk_ = (static_cast<ObDMLStmt&>(stmt)).is_bulk();
|
||||
} else if (stmt.is_insert_stmt() || stmt.is_update_stmt() || stmt.is_delete_stmt()) {
|
||||
ObDelUpdStmt &dml_stmt = static_cast<ObDelUpdStmt&>(stmt);
|
||||
OZ (into_exprs_.assign(dml_stmt.get_returning_into_exprs()));
|
||||
is_bulk_ = (static_cast<ObDMLStmt&>(stmt)).is_bulk();
|
||||
}
|
||||
|
||||
bool need_check = !into_exprs_.empty() && !is_dynamic_sql;
|
||||
if (OB_SUCC(ret) && need_check) {
|
||||
ObArray<ObDataType> basic_types;
|
||||
ObBitSet<> basic_into;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < into_exprs_.count(); ++i) {
|
||||
ObRawExpr *expr = into_exprs_.at(i);
|
||||
CK (OB_NOT_NULL(expr));
|
||||
CK (expr->get_result_type().is_valid());
|
||||
if (OB_SUCC(ret)) {
|
||||
pl::ObPLDataType final_type;
|
||||
// T_OBJ_ACCESS_REF expr, access obj type (not user defined type)
|
||||
bool access_obj_type = false;
|
||||
if (expr->is_obj_access_expr()) {
|
||||
// T_OBJ_ACCESS_REF return ObExtendType for object access for writing, get obj type
|
||||
// from %final_type;
|
||||
// see comment in ObPLInto::add_into
|
||||
const auto &access_expr = static_cast<const ObObjAccessRawExpr &>(*expr);
|
||||
OZ(access_expr.get_final_type(final_type));
|
||||
OX(access_obj_type = !final_type.is_user_type());
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (expr->get_result_type().is_ext() && !access_obj_type) {
|
||||
CK (expr->is_obj_access_expr());
|
||||
if (OB_SUCC(ret) && NULL != ns) {
|
||||
const pl::ObUserDefinedType *user_type = NULL;
|
||||
OZ (ns->get_pl_data_type_by_id(final_type.get_user_type_id(), user_type));
|
||||
OZ (ns->expand_data_type(user_type, basic_types));
|
||||
OZ (check_is_pl_jsontype(user_type));
|
||||
}
|
||||
} else {
|
||||
ObDataType type;
|
||||
if (access_obj_type) {
|
||||
type.set_meta_type(final_type.get_data_type()->get_meta_type());
|
||||
type.set_accuracy(final_type.get_data_type()->get_accuracy());
|
||||
} else {
|
||||
type.set_meta_type(expr->get_result_type().get_obj_meta());
|
||||
type.set_accuracy(expr->get_result_type().get_accuracy());
|
||||
}
|
||||
OZ (basic_types.push_back(type));
|
||||
OZ (basic_into.add_member(basic_types.count() - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
OZ (check_into_exprs(stmt, basic_types, basic_into));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,8 @@ public:
|
||||
route_sql_(),
|
||||
is_select_for_update_(false),
|
||||
has_hidden_rowid_(false),
|
||||
stmt_sql_() {}
|
||||
stmt_sql_(),
|
||||
is_bulk_(false) {}
|
||||
virtual ~ExternalRetrieveInfo() {}
|
||||
|
||||
int build(ObStmt &stmt,
|
||||
@ -94,6 +95,7 @@ public:
|
||||
bool is_select_for_update_;
|
||||
bool has_hidden_rowid_;
|
||||
ObString stmt_sql_;
|
||||
bool is_bulk_;
|
||||
};
|
||||
|
||||
enum PsMode
|
||||
@ -164,6 +166,7 @@ public:
|
||||
ObString &get_stmt_sql();
|
||||
bool get_is_select_for_update();
|
||||
inline bool has_hidden_rowid();
|
||||
inline bool is_bulk();
|
||||
/// whether the result is with rows (true for SELECT statement)
|
||||
bool is_with_rows() const;
|
||||
// tell mysql if need to do async end trans
|
||||
@ -621,6 +624,11 @@ inline bool ObResultSet::has_hidden_rowid()
|
||||
return external_retrieve_info_.has_hidden_rowid_;
|
||||
}
|
||||
|
||||
inline bool ObResultSet::is_bulk()
|
||||
{
|
||||
return external_retrieve_info_.is_bulk_;
|
||||
}
|
||||
|
||||
inline bool ObResultSet::is_with_rows() const
|
||||
{
|
||||
return (p_field_columns_->count() > 0 && !is_prepare_stmt());
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -235,6 +235,7 @@ public:
|
||||
TgTimingEvent tg_timing_event_;
|
||||
uint64_t rowid_table_id_;
|
||||
ObString ps_sql_; // sql prepare过后的参数化sql
|
||||
bool is_bulk_;
|
||||
};
|
||||
|
||||
struct PLPrepareCtx
|
||||
@ -338,16 +339,23 @@ public:
|
||||
static int spi_set_package_variable(pl::ObPLExecCtx *ctx,
|
||||
uint64_t package_id,
|
||||
int64_t var_idx,
|
||||
const ObObj &value);
|
||||
const ObObj &value,
|
||||
bool need_deep_copy = false);
|
||||
static int spi_set_package_variable(ObExecContext *exec_ctx,
|
||||
pl::ObPLPackageGuard *guard,
|
||||
uint64_t package_id,
|
||||
int64_t var_idx,
|
||||
const ObObj &value);
|
||||
const ObObj &value,
|
||||
ObIAllocator *allocator = NULL,
|
||||
bool need_deep_copy = false);
|
||||
static int check_and_deep_copy_result(ObIAllocator &alloc,
|
||||
const ObObj &src,
|
||||
ObObj &dst);
|
||||
static int spi_set_variable(pl::ObPLExecCtx *ctx,
|
||||
const ObSqlExpression* expr,
|
||||
const ObObjParam *value,
|
||||
bool is_default = false);
|
||||
bool is_default = false,
|
||||
bool need_copy = false);
|
||||
static int spi_query(pl::ObPLExecCtx *ctx,
|
||||
const char* sql,
|
||||
int64_t type,
|
||||
@ -358,6 +366,7 @@ public:
|
||||
const bool *exprs_not_null_flag = NULL,
|
||||
const int64_t *pl_integer_ranges = NULL,
|
||||
bool is_bulk = false,
|
||||
bool is_type_record = false,
|
||||
bool for_update = false);
|
||||
static int spi_check_autonomous_trans(pl::ObPLExecCtx *ctx);
|
||||
static int spi_prepare(common::ObIAllocator &allocator,
|
||||
@ -382,6 +391,7 @@ public:
|
||||
const int64_t *pl_integer_rangs,
|
||||
bool is_bulk = false,
|
||||
bool is_forall = false,
|
||||
bool is_type_record = false,
|
||||
bool for_update = false);
|
||||
|
||||
static int spi_execute_immediate(pl::ObPLExecCtx *ctx,
|
||||
@ -396,7 +406,8 @@ public:
|
||||
const bool *exprs_not_null_flag,
|
||||
const int64_t *pl_integer_rangs,
|
||||
bool is_bulk = false,
|
||||
bool is_returning = false);
|
||||
bool is_returning = false,
|
||||
bool is_type_record = false);
|
||||
|
||||
static int spi_get_subprogram_cursor_info(pl::ObPLExecCtx *ctx,
|
||||
uint64_t package_id,
|
||||
@ -477,7 +488,8 @@ public:
|
||||
bool is_bulk,
|
||||
int64_t limit,
|
||||
const ObDataType *return_types,
|
||||
int64_t return_type_count);
|
||||
int64_t return_type_count,
|
||||
bool is_type_record = false);
|
||||
static int spi_cursor_close(pl::ObPLExecCtx *ctx,
|
||||
uint64_t package_id,
|
||||
uint64_t routine_id,
|
||||
@ -663,6 +675,7 @@ public:
|
||||
ObSPIOutParams &out_params);
|
||||
|
||||
static void adjust_pl_status_for_xa(sql::ObExecContext &ctx, int &result);
|
||||
static int fill_cursor(ObResultSet &result_set, ObSPICursor *cursor);
|
||||
|
||||
private:
|
||||
static int recreate_implicit_savapoint_if_need(pl::ObPLExecCtx *ctx, int &result);
|
||||
@ -731,6 +744,7 @@ private:
|
||||
const int64_t *pl_integer_rangs,
|
||||
int64_t is_bulk,
|
||||
bool is_forall = false,
|
||||
bool is_type_record = false,
|
||||
bool for_update = false);
|
||||
|
||||
static int dbms_cursor_execute(pl::ObPLExecCtx *ctx,
|
||||
@ -795,7 +809,8 @@ private:
|
||||
bool for_cursor = false,
|
||||
int64_t limit = INT64_MAX,
|
||||
const ObDataType *return_types = nullptr,
|
||||
int64_t return_type_count = 0);
|
||||
int64_t return_type_count = 0,
|
||||
bool is_type_record = false);
|
||||
static int inner_fetch_with_retry(
|
||||
pl::ObPLExecCtx *ctx,
|
||||
ObSPIResultSet &spi_result,
|
||||
@ -813,7 +828,8 @@ private:
|
||||
int64_t limit,
|
||||
int64_t last_exec_time,
|
||||
const ObDataType *return_types = nullptr,
|
||||
int64_t return_type_count = 0);
|
||||
int64_t return_type_count = 0,
|
||||
bool is_type_record = false);
|
||||
|
||||
static int convert_obj(pl::ObPLExecCtx *ctx,
|
||||
ObCastCtx &cast_ctx,
|
||||
@ -845,14 +861,16 @@ private:
|
||||
bool is_forall = false,
|
||||
int64_t limit = INT64_MAX,
|
||||
const ObDataType *return_types = nullptr,
|
||||
int64_t return_type_count = 0);
|
||||
int64_t return_type_count = 0,
|
||||
bool is_type_record = false);
|
||||
|
||||
static int fetch_row(void *result_set,
|
||||
bool is_streaming,
|
||||
int64_t &row_count,
|
||||
ObNewRow &row);
|
||||
|
||||
static int collect_cells(ObNewRow &row,
|
||||
static int collect_cells(pl::ObPLExecCtx &ctx,
|
||||
ObNewRow &row,
|
||||
const ObDataType *result_types,
|
||||
int64_t type_count,
|
||||
const ObIArray<ObDataType> &row_desc,
|
||||
@ -871,23 +889,40 @@ private:
|
||||
ObCastCtx &cast_ctx,
|
||||
ObIArray<ObObj> &obj_array,
|
||||
const ObDataType *return_types,
|
||||
int64_t return_type_count);
|
||||
int64_t return_type_count,
|
||||
bool is_type_record = false);
|
||||
|
||||
static int get_package_var_info_by_expr(const ObSqlExpression *expr,
|
||||
uint64_t &package_id,
|
||||
uint64_t &var_idx);
|
||||
static int store_result(ObIArray<pl::ObPLCollection*> &bulk_tables,
|
||||
static int store_result(pl::ObPLExecCtx *ctx,
|
||||
ObIArray<pl::ObPLCollection*> &bulk_tables,
|
||||
int64_t row_count,
|
||||
int64_t column_count,
|
||||
const ObIArray<ObObj> &obj_array,
|
||||
bool append_mode);
|
||||
ObIArray<ObObj> &obj_array,
|
||||
bool append_mode,
|
||||
bool is_type_record);
|
||||
|
||||
static int store_datums(ObObj &dest_addr, const ObIArray<ObObj> &result);
|
||||
static int store_into_result(pl::ObPLExecCtx *ctx,
|
||||
ObCastCtx &cast_ctx,
|
||||
ObNewRow &cur_row,
|
||||
const ObSqlExpression **into_exprs,
|
||||
const ObDataType *column_types,
|
||||
int64_t type_count,
|
||||
int64_t into_count,
|
||||
const bool *exprs_not_null,
|
||||
const int64_t *pl_integer_ranges,
|
||||
const ObDataType *return_types,
|
||||
int64_t return_type_count,
|
||||
int64_t actual_column_count,
|
||||
ObIArray<ObDataType> &row_desc,
|
||||
bool is_type_record);
|
||||
|
||||
static int store_datums(ObObj &dest_addr, const ObIArray<ObObj> &result,
|
||||
ObIAllocator *alloc, bool is_schema_object);
|
||||
|
||||
static int store_datum(int64_t ¤t_addr, const ObObj &obj);
|
||||
|
||||
static int fill_cursor(ObResultSet &result_set, ObSPICursor *cursor);
|
||||
|
||||
static const ObPostExprItem &get_last_expr_item(const ObSqlExpression &expr);
|
||||
|
||||
static const ObInfixExprItem &get_first_expr_item(const ObSqlExpression &expr);
|
||||
@ -954,7 +989,8 @@ private:
|
||||
bool is_bulk,
|
||||
int64_t limit,
|
||||
const ObDataType *return_types = nullptr,
|
||||
int64_t return_type_count = 0);
|
||||
int64_t return_type_count = 0,
|
||||
bool is_type_record = false);
|
||||
|
||||
|
||||
static int check_package_dest_and_deep_copy(pl::ObPLExecCtx &ctx,
|
||||
|
@ -326,11 +326,12 @@ int ObSql::fill_result_set(ObResultSet &result_set,
|
||||
LOG_WARN("fail to get expr", K(ret), K(i), K(size));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ObCollationType charsetnr;
|
||||
if (OB_FAIL(ObCharset::get_default_collation(expr->get_collation_type(), charsetnr))) {
|
||||
LOG_WARN("fail to get table item charset collation", K(expr->get_collation_type()), K(i), K(ret));
|
||||
if (ob_is_string_or_lob_type(expr->get_data_type())
|
||||
&& CS_TYPE_BINARY != expr->get_collation_type()
|
||||
&& ObCharset::is_valid_collation(collation_type)) {
|
||||
field.charsetnr_ = static_cast<uint16_t>(collation_type);
|
||||
} else {
|
||||
field.charsetnr_ = static_cast<uint16_t>(charsetnr);
|
||||
field.charsetnr_ = static_cast<uint16_t>(expr->get_collation_type());
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
@ -433,115 +434,119 @@ int ObSql::fill_result_set(ObResultSet &result_set,
|
||||
case stmt::T_CALL_PROCEDURE: {
|
||||
ObCallProcedureStmt &call_stmt = static_cast<ObCallProcedureStmt&>(basic_stmt);
|
||||
ObString tname = ObString::make_string("procedure");
|
||||
if (NULL == call_stmt.get_call_proc_info()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("call proc info is null", K(ret));
|
||||
} else {
|
||||
int64_t size = call_stmt.get_call_proc_info()->get_output_count();
|
||||
field.charsetnr_ = CS_TYPE_UTF8MB4_GENERAL_CI;
|
||||
|
||||
int64_t size = call_stmt.get_output_count();
|
||||
field.charsetnr_ = CS_TYPE_UTF8MB4_GENERAL_CI;
|
||||
if (0 == size) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (0 == call_stmt.get_output_count()) {
|
||||
if (OB_SUCC(ret) && OB_FAIL(result_set.reserve_field_columns(size))) {
|
||||
LOG_WARN("reserve field columns failed", K(ret), K(size));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < size; ++i) {
|
||||
ObCollationType charsetnr;
|
||||
ObDataType *type = call_stmt.get_call_proc_info()->get_out_type().at(i).get_data_type();
|
||||
ObObjType out_obj_type = call_stmt.get_call_proc_info()->get_out_type().at(i).get_obj_type();
|
||||
if (ObUnknownType == out_obj_type
|
||||
|| ObExtendType == out_obj_type) {
|
||||
// do nothing ...
|
||||
} else if (OB_NOT_NULL(type)) {
|
||||
if (ob_is_string_or_lob_type(out_obj_type)
|
||||
&& CS_TYPE_ANY == type->get_collation_type()) {
|
||||
charsetnr = ObCharset::is_valid_collation(collation_type)
|
||||
? collation_type
|
||||
: CS_TYPE_UTF8MB4_BIN;
|
||||
} else {
|
||||
OZ (ObCharset::get_default_collation(type->get_collation_type(), charsetnr));
|
||||
}
|
||||
OX (field.charsetnr_ = static_cast<uint16_t>(charsetnr));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
field.type_.set_type(out_obj_type);
|
||||
if (OB_NOT_NULL(type)) {
|
||||
field.accuracy_ = type->get_accuracy();
|
||||
// Setup Collation and Collation levl
|
||||
if (ob_is_string_or_lob_type(out_obj_type)
|
||||
|| ob_is_raw(out_obj_type)
|
||||
|| ob_is_enum_or_set_type(out_obj_type)) {
|
||||
field.type_.set_collation_type(type->get_collation_type());
|
||||
field.type_.set_collation_level(type->get_collation_level());
|
||||
}
|
||||
}
|
||||
if (ObExtendType == out_obj_type) {
|
||||
field.length_ = field.accuracy_.get_length();
|
||||
} else if (ObCharType == out_obj_type
|
||||
|| ObVarcharType == out_obj_type
|
||||
|| ob_is_nstring_type(out_obj_type)) {
|
||||
if (-1 == field.accuracy_.get_length()) {
|
||||
field.length_ = ObCharType == out_obj_type ?
|
||||
OB_MAX_ORACLE_CHAR_LENGTH_BYTE : OB_MAX_ORACLE_VARCHAR_LENGTH;
|
||||
} else {
|
||||
field.length_ = field.accuracy_.get_length();
|
||||
}
|
||||
} else if (ob_is_enum_or_set_type(out_obj_type)) {
|
||||
CK (OB_NOT_NULL(type));
|
||||
OZ (common::ObField::get_field_mb_length(field.type_.get_type(),
|
||||
field.accuracy_,
|
||||
type->get_collation_type(),
|
||||
field.length_));
|
||||
OX (field.type_.set_type(ObVarcharType));
|
||||
} else {
|
||||
OZ (common::ObField::get_field_mb_length(field.type_.get_type(),
|
||||
field.accuracy_,
|
||||
common::CS_TYPE_INVALID,
|
||||
field.length_));
|
||||
}
|
||||
// Setup Scale
|
||||
if (OB_SUCC(ret)) {
|
||||
if (ObVarcharType == field.type_.get_type()) {
|
||||
field.type_.set_varchar(type_name);
|
||||
} else if (ObNumberType == field.type_.get_type()) {
|
||||
field.type_.set_number(number);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(ob_write_string(alloc, tname, field.tname_))) {
|
||||
LOG_WARN("fail to alloc string", K(call_stmt.get_call_proc_info()->get_out_name().at(i)), K(ret));
|
||||
} else if (OB_FAIL(ob_write_string(alloc, tname, field.org_tname_))) {
|
||||
LOG_WARN("fail to alloc string", K(call_stmt.get_call_proc_info()->get_out_name().at(i)), K(ret));
|
||||
} else if (OB_FAIL(ob_write_string(alloc, call_stmt.get_call_proc_info()->get_out_name().at(i), field.cname_))) {
|
||||
LOG_WARN("fail to alloc string", K(call_stmt.get_call_proc_info()->get_out_name().at(i)), K(ret));
|
||||
} else if (OB_FAIL(ob_write_string(alloc, call_stmt.get_call_proc_info()->get_out_name().at(i), field.org_cname_))) {
|
||||
LOG_WARN("fail to alloc string", K(call_stmt.get_call_proc_info()->get_out_name().at(i)), K(ret));
|
||||
} else if (OB_FAIL(ob_write_string(alloc, call_stmt.get_call_proc_info()->get_out_type_name().at(i), field.type_name_))) {
|
||||
LOG_WARN("fail to alloc string", K(call_stmt.get_call_proc_info()->get_out_type_name().at(i)), K(ret));
|
||||
} else if (OB_FAIL(ob_write_string(alloc, call_stmt.get_call_proc_info()->get_out_type_owner().at(i), field.type_owner_))) {
|
||||
LOG_WARN("fail to alloc string", K(call_stmt.get_call_proc_info()->get_out_type_owner().at(i)), K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(result_set.add_field_column(field))) {
|
||||
LOG_WARN("fail to add field column to result_set.", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
field.cname_.assign(NULL, 0);
|
||||
field.org_cname_.assign(NULL, 0);
|
||||
field.dname_.assign(NULL, 0);
|
||||
field.tname_.assign(NULL, 0);
|
||||
field.org_tname_.assign(NULL, 0);
|
||||
field.type_.reset();
|
||||
field.type_.set_type(ObExtendType);
|
||||
field.type_name_.assign(NULL, 0);
|
||||
field.type_owner_.assign(NULL, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && OB_FAIL(result_set.reserve_field_columns(size))) {
|
||||
LOG_WARN("reserve field columns failed", K(ret), K(size));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < size; ++i) {
|
||||
ObCollationType charsetnr;
|
||||
ObDataType *type = call_stmt.get_out_type().at(i).get_data_type();
|
||||
ObObjType out_obj_type = call_stmt.get_out_type().at(i).get_obj_type();
|
||||
if (ObUnknownType == out_obj_type
|
||||
|| ObExtendType == out_obj_type) {
|
||||
// do nothing ...
|
||||
} else if (OB_NOT_NULL(type)) {
|
||||
if (ob_is_string_or_lob_type(out_obj_type)
|
||||
&& CS_TYPE_ANY == type->get_collation_type()) {
|
||||
charsetnr = ObCharset::is_valid_collation(collation_type)
|
||||
? collation_type
|
||||
: CS_TYPE_UTF8MB4_BIN;
|
||||
} else {
|
||||
OZ (ObCharset::get_default_collation(type->get_collation_type(), charsetnr));
|
||||
}
|
||||
OX (field.charsetnr_ = static_cast<uint16_t>(charsetnr));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
field.type_.set_type(out_obj_type);
|
||||
if (OB_NOT_NULL(type)) {
|
||||
field.accuracy_ = type->get_accuracy();
|
||||
// Setup Collation and Collation levl
|
||||
if (ob_is_string_or_lob_type(out_obj_type)
|
||||
|| ob_is_raw(out_obj_type)
|
||||
|| ob_is_enum_or_set_type(out_obj_type)) {
|
||||
field.type_.set_collation_type(type->get_collation_type());
|
||||
field.type_.set_collation_level(type->get_collation_level());
|
||||
}
|
||||
}
|
||||
if (ObExtendType == out_obj_type) {
|
||||
field.length_ = field.accuracy_.get_length();
|
||||
} else if (ObCharType == out_obj_type
|
||||
|| ObVarcharType == out_obj_type
|
||||
|| ob_is_nstring_type(out_obj_type)) {
|
||||
if (-1 == field.accuracy_.get_length()) {
|
||||
field.length_ = ObCharType == out_obj_type ?
|
||||
OB_MAX_ORACLE_CHAR_LENGTH_BYTE : OB_MAX_ORACLE_VARCHAR_LENGTH;
|
||||
} else {
|
||||
field.length_ = field.accuracy_.get_length();
|
||||
}
|
||||
} else if (ob_is_enum_or_set_type(out_obj_type)) {
|
||||
CK (OB_NOT_NULL(type));
|
||||
OZ (common::ObField::get_field_mb_length(field.type_.get_type(),
|
||||
field.accuracy_,
|
||||
type->get_collation_type(),
|
||||
field.length_));
|
||||
OX (field.type_.set_type(ObVarcharType));
|
||||
} else {
|
||||
OZ (common::ObField::get_field_mb_length(field.type_.get_type(),
|
||||
field.accuracy_,
|
||||
common::CS_TYPE_INVALID,
|
||||
field.length_));
|
||||
}
|
||||
// Setup Scale
|
||||
if (OB_SUCC(ret)) {
|
||||
if (ObVarcharType == field.type_.get_type()) {
|
||||
field.type_.set_varchar(type_name);
|
||||
} else if (ObNumberType == field.type_.get_type()) {
|
||||
field.type_.set_number(number);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(ob_write_string(alloc, tname, field.tname_))) {
|
||||
LOG_WARN("fail to alloc string", K(call_stmt.get_out_name().at(i)), K(ret));
|
||||
} else if (OB_FAIL(ob_write_string(alloc, tname, field.org_tname_))) {
|
||||
LOG_WARN("fail to alloc string", K(call_stmt.get_out_name().at(i)), K(ret));
|
||||
} else if (OB_FAIL(ob_write_string(alloc, call_stmt.get_out_name().at(i), field.cname_))) {
|
||||
LOG_WARN("fail to alloc string", K(call_stmt.get_out_name().at(i)), K(ret));
|
||||
} else if (OB_FAIL(ob_write_string(alloc, call_stmt.get_out_name().at(i), field.org_cname_))) {
|
||||
LOG_WARN("fail to alloc string", K(call_stmt.get_out_name().at(i)), K(ret));
|
||||
} else if (OB_FAIL(ob_write_string(alloc, call_stmt.get_out_type_name().at(i), field.type_name_))) {
|
||||
LOG_WARN("fail to alloc string", K(call_stmt.get_out_type_name().at(i)), K(ret));
|
||||
} else if (OB_FAIL(ob_write_string(alloc, call_stmt.get_out_type_owner().at(i), field.type_owner_))) {
|
||||
LOG_WARN("fail to alloc string", K(call_stmt.get_out_type_owner().at(i)), K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(result_set.add_field_column(field))) {
|
||||
LOG_WARN("fail to add field column to result_set.", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
field.cname_.assign(NULL, 0);
|
||||
field.org_cname_.assign(NULL, 0);
|
||||
field.dname_.assign(NULL, 0);
|
||||
field.tname_.assign(NULL, 0);
|
||||
field.org_tname_.assign(NULL, 0);
|
||||
field.type_.reset();
|
||||
field.type_.set_type(ObExtendType);
|
||||
field.type_name_.assign(NULL, 0);
|
||||
field.type_owner_.assign(NULL, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
@ -573,7 +578,7 @@ int ObSql::fill_result_set(ObResultSet &result_set,
|
||||
OX (param_field.inout_mode_ = ObRoutineParamInOut::SP_PARAM_INOUT);
|
||||
OZ (result_set.add_field_column(column_field),
|
||||
K(i), K(question_marks_count), K(column_field));
|
||||
} else if (OB_NOT_NULL(call_stmt) && call_stmt->is_out_param(i)) {
|
||||
} else if (OB_NOT_NULL(call_stmt) && call_stmt->get_call_proc_info()->is_out_param(i)) {
|
||||
OX (param_field.inout_mode_ = ObRoutineParamInOut::SP_PARAM_INOUT);
|
||||
}
|
||||
OZ (result_set.add_param_column(param_field),
|
||||
@ -2069,6 +2074,9 @@ int ObSql::handle_ps_execute(const ObPsStmtId client_stmt_id,
|
||||
// call procedure stmt call always parse as dynamic sql
|
||||
context.is_dynamic_sql_ = true;
|
||||
}
|
||||
if (stmt::T_CALL_PROCEDURE == stmt_type && !context.is_execute_call_stmt_) {
|
||||
context.is_execute_call_stmt_ = true;
|
||||
}
|
||||
ObParser parser(allocator, session.get_sql_mode(),
|
||||
session.get_local_collation_connection());
|
||||
ParseResult parse_result;
|
||||
|
@ -547,7 +547,7 @@ public:
|
||||
anonymous_view_count_(0),
|
||||
all_user_variable_(),
|
||||
has_udf_(false),
|
||||
has_pl_udf_(false),
|
||||
disable_udf_parallel_(false),
|
||||
has_is_table_(false),
|
||||
reference_obj_tables_(),
|
||||
is_table_gen_col_with_udf_(false),
|
||||
@ -584,7 +584,7 @@ public:
|
||||
anonymous_view_count_ = 0;
|
||||
all_user_variable_.reset();
|
||||
has_udf_ = false;
|
||||
has_pl_udf_ = false;
|
||||
disable_udf_parallel_ = false;
|
||||
has_is_table_ = false;
|
||||
sql_schema_guard_.reset();
|
||||
reference_obj_tables_.reset();
|
||||
@ -657,7 +657,7 @@ public:
|
||||
common::ObSArray<ObUserVarIdentRawExpr *, common::ModulePageAllocator, true> all_user_variable_;
|
||||
common::hash::ObHashMap<uint64_t, ObObj, common::hash::NoPthreadDefendMode> calculable_expr_results_;
|
||||
bool has_udf_;
|
||||
bool has_pl_udf_; //used to mark query has pl udf
|
||||
bool disable_udf_parallel_; //used to deterministic pl udf parallel execute
|
||||
bool has_is_table_; // used to mark query has information schema table
|
||||
ObSqlSchemaGuard sql_schema_guard_;
|
||||
share::schema::ObReferenceObjTable reference_obj_tables_;
|
||||
|
@ -494,7 +494,7 @@ int ObSQLUtils::calc_sql_expression_without_row(
|
||||
LOG_WARN("session is NULL", K(ret));
|
||||
} else {
|
||||
const sql::ObExpr *new_expr = expr.get_expr();
|
||||
exec_ctx.get_physical_plan_ctx()->set_cur_time(ObTimeUtility::current_time());
|
||||
exec_ctx.get_physical_plan_ctx()->set_cur_time(ObTimeUtility::current_time(), *exec_ctx.get_my_session());
|
||||
if (NULL == new_expr) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("static engine should have implement this function. unexpected null", K(ret));
|
||||
|
@ -512,7 +512,7 @@ int ObOptimizer::check_pdml_supported_feature(const ObDMLStmt &stmt,
|
||||
} else if (stmt_has_dblink) {
|
||||
is_use_pdml = false;
|
||||
ctx_.set_has_dblink(true);
|
||||
} else if (ctx_.contain_user_nested_sql()) {
|
||||
} else if (!ctx_.has_trigger() && ctx_.contain_user_nested_sql()) {
|
||||
//user nested sql can't use PDML plan, force to use DAS plan
|
||||
//if online ddl has pl udf, only this way, allow it use PDML plan
|
||||
//such as:
|
||||
@ -521,6 +521,11 @@ int ObOptimizer::check_pdml_supported_feature(const ObDMLStmt &stmt,
|
||||
//create index with PL UDF allow to use PDML plan during build index table
|
||||
is_use_pdml = false;
|
||||
ctx_.add_plan_note(PDML_DISABLED_BY_NESTED_SQL);
|
||||
} else if (ctx_.has_trigger() && !ctx_.is_allow_parallel_trigger()) {
|
||||
// if sql linked trigger, and trigger do not access package var, sequence, sql stmt etc..,
|
||||
// allow it use PDML plan
|
||||
is_use_pdml = false;
|
||||
ctx_.add_plan_note(PDML_DISABLED_BY_NESTED_SQL);
|
||||
} else if (stmt::T_DELETE == stmt.get_stmt_type()) {
|
||||
//
|
||||
// if no trigger, no foreign key, delete can do pdml, even if with local unique index
|
||||
@ -758,7 +763,7 @@ int ObOptimizer::check_whether_contain_nested_sql(const ObDMLStmt &stmt)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObDelUpdStmt *del_upd_stmt = nullptr;
|
||||
if (stmt.get_query_ctx()->has_pl_udf_) {
|
||||
if (stmt.get_query_ctx()->disable_udf_parallel_) {
|
||||
ctx_.set_has_pl_udf(true);
|
||||
}
|
||||
if (ObSQLUtils::is_nested_sql(ctx_.get_exec_ctx())) {
|
||||
@ -775,6 +780,7 @@ int ObOptimizer::check_whether_contain_nested_sql(const ObDMLStmt &stmt)
|
||||
const ObTableSchema *table_schema = nullptr;
|
||||
ObSQLSessionInfo *session = ctx_.get_session_info();
|
||||
bool trigger_exists = false;
|
||||
bool is_forbid_parallel = false;
|
||||
if (OB_ISNULL(table_info) || OB_ISNULL(schema_guard) || OB_ISNULL(session)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("sql schema guard is nullptr", K(ret), K(table_info), K(schema_guard), K(session));
|
||||
@ -793,6 +799,13 @@ int ObOptimizer::check_whether_contain_nested_sql(const ObDMLStmt &stmt)
|
||||
ctx_.set_has_trigger(true);
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && trigger_exists) {
|
||||
if (OB_FAIL(table_schema->is_allow_parallel_of_trigger(*schema_guard, is_forbid_parallel))) {
|
||||
LOG_WARN("check allow parallel failed", K(ret));
|
||||
} else if (!is_forbid_parallel) {
|
||||
ctx_.set_allow_parallel_trigger(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -462,6 +462,8 @@ ObOptimizerContext(ObSQLSessionInfo *session_info,
|
||||
bool has_trigger() const { return has_trigger_; }
|
||||
void set_has_pl_udf(bool v) { has_pl_udf_ = v; }
|
||||
bool has_pl_udf() const { return has_pl_udf_; }
|
||||
void set_allow_parallel_trigger(bool v) { is_allow_parallel_trigger_ = v; }
|
||||
bool is_allow_parallel_trigger() const { return is_allow_parallel_trigger_; }
|
||||
void set_has_dblink(bool v) { has_dblink_ = v; }
|
||||
bool has_dblink() const { return has_dblink_; }
|
||||
void set_has_subquery_in_function_table(bool v) { has_subquery_in_function_table_ = v; }
|
||||
@ -543,6 +545,7 @@ private:
|
||||
int8_t has_pl_udf_ : 1; //this sql has pl user defined function
|
||||
int8_t has_subquery_in_function_table_ : 1; //this stmt has function table
|
||||
int8_t has_dblink_ : 1; //this stmt has dblink table
|
||||
int8_t is_allow_parallel_trigger_ : 1; //this sql linked trigger can parallel execute
|
||||
};
|
||||
};
|
||||
bool has_for_update_;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "pl/ob_pl.h"
|
||||
#include "pl/ob_pl_package.h"
|
||||
#include "observer/table/ob_table_cache.h"
|
||||
#include "sql/resolver/cmd/ob_call_procedure_stmt.h"
|
||||
|
||||
#define USING_LOG_PREFIX SQL_PC
|
||||
|
||||
|
@ -18,7 +18,7 @@ LIB_CACHE_OBJ_DEF(NS_ANON, "ANON", pl::ObPLObjectKey, pl::ObPLObjectSet, pl::ObP
|
||||
LIB_CACHE_OBJ_DEF(NS_TRGR, "TRGR", pl::ObPLObjectKey, pl::ObPLObjectSet, pl::ObPLPackage, ObNewModIds::OB_SQL_PHY_PL_OBJ) // trigger cache
|
||||
LIB_CACHE_OBJ_DEF(NS_PKG, "PKG", pl::ObPLObjectKey, pl::ObPLObjectSet, pl::ObPLPackage, ObNewModIds::OB_SQL_PHY_PL_OBJ) // package cache
|
||||
LIB_CACHE_OBJ_DEF(NS_TABLEAPI, "TABLEAPI", table::ObTableApiCacheKey, table::ObTableApiCacheNode, table::ObTableApiCacheObj, "OB_TABLEAPI_OBJ") // tableapi cache
|
||||
|
||||
LIB_CACHE_OBJ_DEF(NS_CALLSTMT, "CALLSTMT", pl::ObPLObjectKey, pl::ObPLObjectSet, ObCallProcedureInfo, ObNewModIds::OB_SQL_PHY_PL_OBJ) // call stmt cache
|
||||
#endif /*LIB_CACHE_OBJ_DEF*/
|
||||
|
||||
#ifndef OCEANBASE_SQL_PLAN_CACHE_OB_LIB_CACHE_REGISTER_
|
||||
|
@ -64,7 +64,8 @@ const char* ObCacheRefHandleMgr::handle_name(const CacheRefHandleID handle_id)
|
||||
"lc_ref_cache_obj_stat_handle",
|
||||
"plan_baseline_handle",
|
||||
"tableapi_node_handle",
|
||||
"sql_plan_handle"
|
||||
"sql_plan_handle",
|
||||
"callstmt_handle"
|
||||
};
|
||||
static_assert(sizeof(handle_names)/sizeof(const char*) == MAX_HANDLE, "invalid handle name array");
|
||||
if (handle_id < MAX_HANDLE) {
|
||||
|
@ -129,6 +129,7 @@ enum CacheRefHandleID
|
||||
PLAN_BASELINE_HANDLE,
|
||||
TABLEAPI_NODE_HANDLE,
|
||||
SQL_PLAN_HANDLE,
|
||||
CALLSTMT_HANDLE,
|
||||
MAX_HANDLE
|
||||
};
|
||||
|
||||
|
@ -597,8 +597,6 @@ int add_procs_priv_in_dml(
|
||||
if (OB_ISNULL(dml_stmt) || OB_ISNULL(dml_stmt->get_query_ctx())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret));
|
||||
} else if (!dml_stmt->get_query_ctx()->has_pl_udf_) {
|
||||
// do nothing
|
||||
} else if (dml_stmt->get_relation_exprs(relation_exprs)) {
|
||||
LOG_WARN("failed to get relation exprs", K(ret));
|
||||
}
|
||||
@ -2695,10 +2693,10 @@ int get_call_ora_need_privs(
|
||||
int ret = OB_SUCCESS;
|
||||
ObOraNeedPriv need_priv;
|
||||
ObPackedObjPriv packed_privs = 0;
|
||||
const ObCallProcedureStmt * call_stmt = dynamic_cast<const ObCallProcedureStmt*>(basic_stmt);
|
||||
if (call_stmt != NULL) {
|
||||
need_priv.db_name_ = call_stmt->get_db_name();
|
||||
uint64_t pkg_id = call_stmt->get_package_id();
|
||||
ObCallProcedureStmt * call_stmt = const_cast<ObCallProcedureStmt *>(dynamic_cast<const ObCallProcedureStmt*>(basic_stmt));
|
||||
if (call_stmt != NULL && call_stmt->get_call_proc_info() != NULL) {
|
||||
need_priv.db_name_ = call_stmt->get_call_proc_info()->get_db_name();
|
||||
uint64_t pkg_id = call_stmt->get_call_proc_info()->get_package_id();
|
||||
/* 对于sys库的package,不需要权限 */
|
||||
if (need_priv.db_name_ == OB_SYS_DATABASE_NAME
|
||||
&& (OB_INVALID_ID == pkg_id
|
||||
@ -2727,11 +2725,11 @@ int get_call_ora_need_privs(
|
||||
}
|
||||
} else {
|
||||
need_priv.grantee_id_ = user_id;
|
||||
if (call_stmt->get_package_id() != OB_INVALID_ID) {
|
||||
need_priv.obj_id_ = call_stmt->get_package_id();
|
||||
if (call_stmt->get_call_proc_info()->get_package_id() != OB_INVALID_ID) {
|
||||
need_priv.obj_id_ = call_stmt->get_call_proc_info()->get_package_id();
|
||||
need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::PACKAGE);
|
||||
} else {
|
||||
need_priv.obj_id_ = call_stmt->get_routine_id();
|
||||
need_priv.obj_id_ = call_stmt->get_call_proc_info()->get_routine_id();
|
||||
need_priv.obj_type_ = static_cast<uint64_t>(ObObjectType::PROCEDURE);
|
||||
}
|
||||
need_priv.obj_level_ = OBJ_LEVEL_FOR_TAB_PRIV;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "pl/ob_pl_package.h"
|
||||
#include "observer/ob_req_time_service.h"
|
||||
#include "pl/ob_pl_compile.h"
|
||||
#include "pl/pl_cache/ob_pl_cache_mgr.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -50,12 +51,13 @@ int ObCallProcedureResolver::check_param_expr_legal(ObRawExpr *param)
|
||||
}
|
||||
int ObCallProcedureResolver::resolve_cparams(const ParseNode *params_node,
|
||||
const ObRoutineInfo *routine_info,
|
||||
ObCallProcedureStmt *stmt)
|
||||
ObCallProcedureInfo *call_proc_info,
|
||||
ObIArray<ObRawExpr*> ¶ms)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
CK (OB_NOT_NULL(routine_info));
|
||||
CK (OB_NOT_NULL(stmt));
|
||||
ObArray<ObRawExpr*> params;
|
||||
CK (OB_NOT_NULL(call_proc_info));
|
||||
|
||||
// Step 1: 初始化参数列表
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < routine_info->get_param_count(); ++i) {
|
||||
OZ (params.push_back(NULL));
|
||||
@ -103,8 +105,7 @@ int ObCallProcedureResolver::resolve_cparams(const ParseNode *params_node,
|
||||
OX (params.at(i) = default_expr);
|
||||
}
|
||||
}
|
||||
// Step 4: 将参数数组设置到stmt中
|
||||
OZ (stmt->add_params(params));
|
||||
|
||||
if (OB_SUCC(ret)) { // 判断所有参数没有复杂表达式参数
|
||||
bool v = true;
|
||||
for (int64_t i = 0; v && OB_SUCC(ret) && i < params.count(); i ++) {
|
||||
@ -120,7 +121,7 @@ int ObCallProcedureResolver::resolve_cparams(const ParseNode *params_node,
|
||||
v = false;
|
||||
}
|
||||
} // for end
|
||||
stmt->set_can_direct_use_param(v);
|
||||
call_proc_info->set_can_direct_use_param(v);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -252,6 +253,92 @@ int ObCallProcedureResolver::resolve_param_exprs(const ParseNode *params_node,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObCallProcedureResolver::generate_pl_cache_ctx(pl::ObPLCacheCtx &pc_ctx)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(schema_checker_) || OB_ISNULL(session_info_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("argument is NULL", K(schema_checker_), K(session_info_), K(ret));
|
||||
} else if (OB_ISNULL(schema_checker_->get_schema_mgr())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("argument is NULL", K(ret));
|
||||
} else {
|
||||
pc_ctx.session_info_ = session_info_;
|
||||
pc_ctx.schema_guard_ = schema_checker_->get_schema_mgr();
|
||||
pc_ctx.cache_params_ = const_cast<ParamStore *>(params_.param_list_);
|
||||
pc_ctx.raw_sql_ = params_.cur_sql_;
|
||||
pc_ctx.key_.namespace_ = ObLibCacheNameSpace::NS_CALLSTMT;
|
||||
pc_ctx.key_.db_id_ = session_info_->get_database_id();
|
||||
pc_ctx.key_.sessid_ = 0;
|
||||
pc_ctx.key_.key_id_ = OB_INVALID_ID;
|
||||
pc_ctx.key_.name_ = params_.cur_sql_;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObCallProcedureResolver::add_call_proc_info(ObCallProcedureInfo *call_info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObPlanCache *plan_cache = NULL;
|
||||
pl::ObPLCacheCtx pc_ctx;
|
||||
if (OB_ISNULL(session_info_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("argument is NULL", K(ret));
|
||||
} else if (OB_ISNULL(plan_cache = session_info_->get_plan_cache())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("argument is NULL", K(ret));
|
||||
} else if (OB_FAIL(generate_pl_cache_ctx(pc_ctx))) {
|
||||
LOG_WARN("generate pl cache ctx failed", K(ret));
|
||||
} else if (OB_FAIL(pl::ObPLCacheMgr::add_pl_cache(plan_cache, call_info, pc_ctx))) {
|
||||
if (OB_SQL_PC_PLAN_DUPLICATE == ret) {
|
||||
ret = OB_SUCCESS;
|
||||
LOG_DEBUG("this plan has been added by others, need not add again", KPC(call_info));
|
||||
} else if (OB_REACH_MEMORY_LIMIT == ret || OB_SQL_PC_PLAN_SIZE_LIMIT == ret) {
|
||||
if (REACH_TIME_INTERVAL(1000000)) { //1s, 当内存达到上限时, 该日志打印会比较频繁, 所以以1s为间隔打印
|
||||
LOG_DEBUG("can't add plan to plan cache",
|
||||
K(ret), K(call_info->get_mem_size()), K(pc_ctx.key_),
|
||||
K(plan_cache->get_mem_used()));
|
||||
}
|
||||
ret = OB_SUCCESS;
|
||||
} else if (is_not_supported_err(ret)) {
|
||||
ret = OB_SUCCESS;
|
||||
LOG_DEBUG("plan cache don't support add this kind of plan now", KPC(call_info));
|
||||
} else {
|
||||
if (OB_REACH_MAX_CONCURRENT_NUM != ret) { //如果是达到限流上限, 则将错误码抛出去
|
||||
ret = OB_SUCCESS; //add plan出错, 覆盖错误码, 确保因plan cache失败不影响正常执行路径
|
||||
LOG_WARN("Failed to add plan to ObPlanCache", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObCallProcedureResolver::find_call_proc_info(ObCallProcedureStmt &stmt)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObPlanCache *plan_cache = NULL;
|
||||
ObCallProcedureInfo *call_proc_info = NULL;
|
||||
pl::ObPLCacheCtx pc_ctx;
|
||||
if (OB_ISNULL(session_info_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("argument is NULL", K(ret));
|
||||
} else if (OB_ISNULL(plan_cache = session_info_->get_plan_cache())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("argument is NULL", K(ret));
|
||||
} else if (OB_FAIL(generate_pl_cache_ctx(pc_ctx))) {
|
||||
LOG_WARN("generate pl cache ctx failed", K(ret));
|
||||
} else if (OB_FAIL(pl::ObPLCacheMgr::get_pl_cache(plan_cache, stmt.get_cacheobj_guard(), pc_ctx))) {
|
||||
LOG_INFO("get pl function by sql failed, will ignore this error",
|
||||
K(ret), K(pc_ctx.key_));
|
||||
ret = OB_ERR_UNEXPECTED != ret ? OB_SUCCESS : ret;
|
||||
} else {
|
||||
call_proc_info = static_cast<ObCallProcedureInfo*>(stmt.get_cacheobj_guard().get_cache_obj());
|
||||
CK (OB_NOT_NULL(call_proc_info));
|
||||
OX (stmt.set_call_proc_info(call_proc_info));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObCallProcedureResolver::resolve(const ParseNode &parse_tree)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -261,8 +348,8 @@ int ObCallProcedureResolver::resolve(const ParseNode &parse_tree)
|
||||
ObString db_name;
|
||||
ObString package_name;
|
||||
ObString sp_name;
|
||||
ObCallProcedureInfo *call_proc_info = NULL;
|
||||
const ObRoutineInfo *proc_info = NULL;
|
||||
|
||||
if (OB_ISNULL(schema_checker_) || OB_ISNULL(session_info_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("argument is NULL", K(schema_checker_), K(session_info_), K(ret));
|
||||
@ -272,192 +359,222 @@ int ObCallProcedureResolver::resolve(const ParseNode &parse_tree)
|
||||
} else if (OB_ISNULL(stmt = create_stmt<ObCallProcedureStmt>())) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_ERROR("create call stmt failed", K(ret));
|
||||
} else if (FALSE_IT(stmt_ = stmt)) {
|
||||
} else if (FALSE_IT(stmt->get_cacheobj_guard().init(CALLSTMT_HANDLE))) {
|
||||
} else if (params_.is_execute_call_stmt_ && 0 != params_.cur_sql_.length() &&
|
||||
OB_FAIL(find_call_proc_info(*stmt))) {
|
||||
LOG_WARN("fail to find call stmt", K(ret));
|
||||
} else if (NULL != stmt->get_call_proc_info()) {
|
||||
// find call procedure info in pl cache.
|
||||
} else {
|
||||
stmt_ = stmt;
|
||||
}
|
||||
// 解析过程名称
|
||||
if (OB_SUCC(ret)) {
|
||||
if (T_SP_ACCESS_NAME != name_node->type_) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("Invalid procedure name node", K(name_node->type_), K(ret));
|
||||
} else {
|
||||
if (OB_FAIL(ObResolverUtils::resolve_sp_access_name(*schema_checker_,
|
||||
session_info_->get_effective_tenant_id(),
|
||||
session_info_->get_database_name(),
|
||||
*name_node,
|
||||
db_name, package_name, sp_name))) {
|
||||
LOG_WARN("resolve sp name failed", K(ret));
|
||||
} else if (db_name.empty() && session_info_->get_database_name().empty()) {
|
||||
ret = OB_ERR_NO_DB_SELECTED;
|
||||
LOG_WARN("no database selected", K(ret), K(db_name));
|
||||
} else {
|
||||
if (!db_name.empty()) {
|
||||
OX (stmt->set_db_name(db_name));
|
||||
} else {
|
||||
OX (stmt->set_db_name(session_info_->get_database_name()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
ObSEArray<ObRawExpr*, 16> expr_params;
|
||||
// 获取routine schem info
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_NOT_NULL(params_node)
|
||||
&& OB_FAIL(resolve_param_exprs(params_node, expr_params))) {
|
||||
LOG_WARN("failed to resolve param exprs", K(ret));
|
||||
} else if (OB_FAIL(ObResolverUtils::get_routine(params_,
|
||||
(*session_info_).get_effective_tenant_id(),
|
||||
(*session_info_).get_database_name(),
|
||||
db_name,
|
||||
package_name,
|
||||
sp_name,
|
||||
ROUTINE_PROCEDURE_TYPE,
|
||||
expr_params,
|
||||
proc_info))) {
|
||||
LOG_WARN("failed to get routine info", K(ret), K(db_name), K(package_name), K(sp_name));
|
||||
} else if (OB_ISNULL(proc_info)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("proc info is null", K(ret), K(db_name), K(package_name), K(sp_name), K(proc_info));
|
||||
} else if (proc_info->has_accessible_by_clause()) {
|
||||
ret = OB_ERR_MISMATCH_SUBPROGRAM;
|
||||
LOG_WARN("PLS-00263: mismatch between string on a subprogram specification and body",
|
||||
K(ret), KPC(proc_info));
|
||||
}
|
||||
if (OB_SUCC(ret) && proc_info->is_udt_routine() && !proc_info->is_udt_static_routine()) {
|
||||
ret = OB_ERR_CALL_WRONG_ARG;
|
||||
LOG_USER_ERROR(OB_ERR_CALL_WRONG_ARG, proc_info->get_routine_name().length(),
|
||||
proc_info->get_routine_name().ptr());
|
||||
}
|
||||
if (OB_SUCC(ret) && proc_info->is_udt_routine()) {
|
||||
stmt->set_is_udt_routine(true);
|
||||
}
|
||||
OZ (ObCacheObjectFactory::alloc(stmt->get_cacheobj_guard(),
|
||||
ObLibCacheNameSpace::NS_CALLSTMT,
|
||||
session_info_->get_effective_tenant_id()));
|
||||
OX (call_proc_info = static_cast<ObCallProcedureInfo*>(stmt->get_cacheobj_guard().get_cache_obj()));
|
||||
CK (OB_NOT_NULL(call_proc_info));
|
||||
|
||||
// 解析过程名称
|
||||
if (OB_SUCC(ret)) {
|
||||
ObSchemaObjVersion obj_version;
|
||||
obj_version.object_id_ = proc_info->get_routine_id();
|
||||
obj_version.object_type_ = proc_info->is_procedure() ? DEPENDENCY_PROCEDURE : DEPENDENCY_FUNCTION;
|
||||
obj_version.version_ = proc_info->get_schema_version();
|
||||
OZ (stmt->add_global_dependency_table(obj_version));
|
||||
}
|
||||
}
|
||||
// 解析参数列表
|
||||
// if (OB_SUCC(ret) && params_.is_execute_call_stmt_) {
|
||||
// OZ (stmt->add_params(expr_params));
|
||||
// OX (stmt->set_can_direct_use_param(true));
|
||||
// } else {
|
||||
OZ (resolve_cparams(params_node, proc_info, stmt));
|
||||
// }
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_INVALID_ID == proc_info->get_package_id()) {
|
||||
//standalone procedure
|
||||
stmt->set_package_id(proc_info->get_package_id());
|
||||
stmt->set_routine_id(proc_info->get_routine_id());
|
||||
} else {
|
||||
//package procedure
|
||||
stmt->set_package_id(proc_info->get_package_id());
|
||||
stmt->set_routine_id(proc_info->get_subprogram_id());
|
||||
}
|
||||
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < proc_info->get_param_count(); ++i) {
|
||||
const ObRoutineParam *param_info = proc_info->get_routine_params().at(i);
|
||||
const ObRawExpr *param_expr = stmt->get_params().at(i);
|
||||
pl::ObPLDataType pl_type;
|
||||
CK (OB_NOT_NULL(param_info));
|
||||
CK (OB_NOT_NULL(param_expr));
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
CK (OB_NOT_NULL(schema_checker_->get_schema_mgr()));
|
||||
CK (OB_NOT_NULL(params_.sql_proxy_));
|
||||
CK (OB_NOT_NULL(params_.allocator_));
|
||||
CK (OB_NOT_NULL(session_info_));
|
||||
OZ (pl::ObPLDataType::transform_from_iparam(param_info,
|
||||
*(schema_checker_->get_schema_mgr()),
|
||||
*(session_info_),
|
||||
*(params_.allocator_),
|
||||
*(params_.sql_proxy_),
|
||||
pl_type));
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (params_.is_prepare_protocol_
|
||||
&& params_.is_prepare_stage_
|
||||
&& param_expr->get_expr_type() != T_QUESTIONMARK) {
|
||||
// do nothing ...
|
||||
} else if (!param_info->is_extern_type()) {
|
||||
if (T_SP_ACCESS_NAME != name_node->type_) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("Invalid procedure name node", K(name_node->type_), K(ret));
|
||||
} else {
|
||||
if (OB_FAIL(ObResolverUtils::resolve_sp_access_name(*schema_checker_,
|
||||
session_info_->get_effective_tenant_id(),
|
||||
session_info_->get_database_name(),
|
||||
*name_node,
|
||||
db_name, package_name, sp_name))) {
|
||||
LOG_WARN("resolve sp name failed", K(ret));
|
||||
} else if (db_name.empty() && session_info_->get_database_name().empty()) {
|
||||
ret = OB_ERR_NO_DB_SELECTED;
|
||||
LOG_WARN("no database selected", K(ret), K(db_name));
|
||||
} else {
|
||||
if (OB_SUCC(ret)) {
|
||||
//not support complex param not in prepare, except default value
|
||||
if (pl_type.is_user_type()) {
|
||||
if (!params_.is_prepare_protocol_
|
||||
&& !param_expr->has_flag(IS_PL_MOCK_DEFAULT_EXPR)) {
|
||||
ret = OB_ERR_CALL_WRONG_ARG;
|
||||
LOG_WARN("PLS-00306: wrong number or types of arguments in call stmt", K(ret));
|
||||
if (!db_name.empty()) {
|
||||
OZ (call_proc_info->set_db_name(db_name));
|
||||
} else {
|
||||
OZ (call_proc_info->set_db_name(session_info_->get_database_name()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
ObSEArray<ObRawExpr*, 16> expr_params;
|
||||
// 获取routine schem info
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_NOT_NULL(params_node)
|
||||
&& OB_FAIL(resolve_param_exprs(params_node, expr_params))) {
|
||||
LOG_WARN("failed to resolve param exprs", K(ret));
|
||||
} else if (OB_FAIL(ObResolverUtils::get_routine(params_,
|
||||
(*session_info_).get_effective_tenant_id(),
|
||||
(*session_info_).get_database_name(),
|
||||
db_name,
|
||||
package_name,
|
||||
sp_name,
|
||||
ROUTINE_PROCEDURE_TYPE,
|
||||
expr_params,
|
||||
proc_info))) {
|
||||
LOG_WARN("failed to get routine info", K(ret), K(db_name), K(package_name), K(sp_name));
|
||||
} else if (OB_ISNULL(proc_info)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("proc info is null", K(ret), K(db_name), K(package_name), K(sp_name), K(proc_info));
|
||||
} else if (proc_info->has_accessible_by_clause()) {
|
||||
ret = OB_ERR_MISMATCH_SUBPROGRAM;
|
||||
LOG_WARN("PLS-00263: mismatch between string on a subprogram specification and body",
|
||||
K(ret), KPC(proc_info));
|
||||
}
|
||||
if (OB_SUCC(ret) && proc_info->is_udt_routine() && !proc_info->is_udt_static_routine()) {
|
||||
ret = OB_ERR_CALL_WRONG_ARG;
|
||||
LOG_USER_ERROR(OB_ERR_CALL_WRONG_ARG, proc_info->get_routine_name().length(),
|
||||
proc_info->get_routine_name().ptr());
|
||||
}
|
||||
if (OB_SUCC(ret) && proc_info->is_udt_routine()) {
|
||||
call_proc_info->set_is_udt_routine(true);
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ObSchemaObjVersion obj_version;
|
||||
obj_version.object_id_ = proc_info->get_routine_id();
|
||||
obj_version.object_type_ = proc_info->is_procedure() ? DEPENDENCY_PROCEDURE : DEPENDENCY_FUNCTION;
|
||||
obj_version.version_ = proc_info->get_schema_version();
|
||||
int64_t tenant_id = session_info_->get_effective_tenant_id();
|
||||
int64_t tenant_schema_version = OB_INVALID_VERSION;
|
||||
int64_t sys_schema_version = OB_INVALID_VERSION;
|
||||
CK (OB_NOT_NULL(schema_checker_->get_schema_mgr()));
|
||||
OZ (schema_checker_->get_schema_mgr()->get_schema_version(tenant_id, tenant_schema_version));
|
||||
OZ (schema_checker_->get_schema_mgr()->get_schema_version(OB_SYS_TENANT_ID, sys_schema_version));
|
||||
OX (call_proc_info->set_tenant_schema_version(tenant_schema_version));
|
||||
OX (call_proc_info->set_sys_schema_version(sys_schema_version));
|
||||
OZ (call_proc_info->init_dependency_table_store(1));
|
||||
OZ (call_proc_info->get_dependency_table().push_back(obj_version));
|
||||
}
|
||||
}
|
||||
ObArray<ObRawExpr*> params;
|
||||
OZ (resolve_cparams(params_node, proc_info, call_proc_info, params));
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_INVALID_ID == proc_info->get_package_id()) {
|
||||
//standalone procedure
|
||||
call_proc_info->set_package_id(proc_info->get_package_id());
|
||||
call_proc_info->set_routine_id(proc_info->get_routine_id());
|
||||
} else {
|
||||
//package procedure
|
||||
call_proc_info->set_package_id(proc_info->get_package_id());
|
||||
call_proc_info->set_routine_id(proc_info->get_subprogram_id());
|
||||
}
|
||||
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < proc_info->get_param_count(); ++i) {
|
||||
const ObRoutineParam *param_info = proc_info->get_routine_params().at(i);
|
||||
const ObRawExpr *param_expr = params.at(i);
|
||||
pl::ObPLDataType pl_type;
|
||||
CK (OB_NOT_NULL(param_info));
|
||||
CK (OB_NOT_NULL(param_expr));
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
CK (OB_NOT_NULL(schema_checker_->get_schema_mgr()));
|
||||
CK (OB_NOT_NULL(params_.sql_proxy_));
|
||||
CK (OB_NOT_NULL(session_info_));
|
||||
OZ (pl::ObPLDataType::transform_from_iparam(param_info,
|
||||
*(schema_checker_->get_schema_mgr()),
|
||||
*(session_info_),
|
||||
*(params_.allocator_),
|
||||
*(params_.sql_proxy_),
|
||||
pl_type));
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (params_.is_prepare_protocol_
|
||||
&& params_.is_prepare_stage_
|
||||
&& param_expr->get_expr_type() != T_QUESTIONMARK) {
|
||||
// do nothing ...
|
||||
} else if (!param_info->is_extern_type()) {
|
||||
} else {
|
||||
if (OB_SUCC(ret)) {
|
||||
//not support complex param not in prepare, except default value
|
||||
if (pl_type.is_user_type()) {
|
||||
if (!params_.is_prepare_protocol_
|
||||
&& !param_expr->has_flag(IS_PL_MOCK_DEFAULT_EXPR)) {
|
||||
ret = OB_ERR_CALL_WRONG_ARG;
|
||||
LOG_WARN("PLS-00306: wrong number or types of arguments in call stmt", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (param_info->is_out_sp_param() || param_info->is_inout_sp_param()) {
|
||||
const ObRawExpr* param = stmt->get_params().at(i);
|
||||
if (lib::is_mysql_mode()
|
||||
&& param->get_expr_type() != T_OP_GET_USER_VAR
|
||||
&& param->get_expr_type() != T_OP_GET_SYS_VAR) {
|
||||
ret = OB_ER_SP_NOT_VAR_ARG;
|
||||
LOG_USER_ERROR(OB_ER_SP_NOT_VAR_ARG, static_cast<int32_t>(i), static_cast<int32_t>(sp_name.length()), sp_name.ptr());
|
||||
LOG_WARN("OUT or INOUT argument for routine is not a variable", K(param->get_expr_type()), K(ret));
|
||||
} else if (param_info->is_sys_refcursor_type()
|
||||
|| (param_info->is_pkg_type() && pl_type.is_cursor_type())) {
|
||||
OZ (stmt->add_out_param(i,
|
||||
param_info->get_mode(),
|
||||
param_info->get_param_name(),
|
||||
pl_type,
|
||||
ObString("SYS_REFCURSOR"),
|
||||
ObString("")));
|
||||
} else if (param_info->is_complex_type()) { // UDT
|
||||
if (param_info->get_type_owner() == session_info_->get_database_id()) {
|
||||
CK (!session_info_->get_database_name().empty());
|
||||
OZ (stmt->add_out_param(i,
|
||||
if (OB_SUCC(ret)) {
|
||||
if (param_info->is_out_sp_param() || param_info->is_inout_sp_param()) {
|
||||
const ObRawExpr* param = params.at(i);
|
||||
if (lib::is_mysql_mode()
|
||||
&& param->get_expr_type() != T_OP_GET_USER_VAR
|
||||
&& param->get_expr_type() != T_OP_GET_SYS_VAR) {
|
||||
ret = OB_ER_SP_NOT_VAR_ARG;
|
||||
LOG_USER_ERROR(OB_ER_SP_NOT_VAR_ARG, static_cast<int32_t>(i), static_cast<int32_t>(sp_name.length()), sp_name.ptr());
|
||||
LOG_WARN("OUT or INOUT argument for routine is not a variable", K(param->get_expr_type()), K(ret));
|
||||
} else if (param_info->is_sys_refcursor_type()
|
||||
|| (param_info->is_pkg_type() && pl_type.is_cursor_type())) {
|
||||
OZ (call_proc_info->add_out_param(i,
|
||||
param_info->get_mode(),
|
||||
param_info->get_param_name(),
|
||||
pl_type,
|
||||
param_info->get_type_name(),
|
||||
session_info_->get_database_name()));
|
||||
} else {
|
||||
const ObDatabaseSchema *db_schema = NULL;
|
||||
CK (OB_NOT_NULL(schema_checker_));
|
||||
CK (OB_NOT_NULL(schema_checker_->get_schema_mgr()));
|
||||
OZ (schema_checker_->get_schema_mgr()->get_database_schema(param_info->get_tenant_id(),
|
||||
param_info->get_type_owner(), db_schema), param_info->get_type_owner());
|
||||
if (OB_SUCC(ret) && OB_ISNULL(db_schema)) {
|
||||
ret = OB_ERR_BAD_DATABASE;
|
||||
LOG_WARN("failed to get type owner", K(param_info->get_type_owner()));
|
||||
ObString("SYS_REFCURSOR"),
|
||||
ObString("")));
|
||||
} else if (param_info->is_complex_type()) { // UDT
|
||||
if (param_info->get_type_owner() == session_info_->get_database_id()) {
|
||||
CK (!session_info_->get_database_name().empty());
|
||||
OZ (call_proc_info->add_out_param(i,
|
||||
param_info->get_mode(),
|
||||
param_info->get_param_name(),
|
||||
pl_type,
|
||||
param_info->get_type_name(),
|
||||
session_info_->get_database_name()));
|
||||
} else {
|
||||
const ObDatabaseSchema *db_schema = NULL;
|
||||
CK (OB_NOT_NULL(schema_checker_));
|
||||
CK (OB_NOT_NULL(schema_checker_->get_schema_mgr()));
|
||||
OZ (schema_checker_->get_schema_mgr()->get_database_schema(param_info->get_tenant_id(),
|
||||
param_info->get_type_owner(), db_schema), param_info->get_type_owner());
|
||||
if (OB_SUCC(ret) && OB_ISNULL(db_schema)) {
|
||||
ret = OB_ERR_BAD_DATABASE;
|
||||
LOG_WARN("failed to get type owner", K(param_info->get_type_owner()));
|
||||
}
|
||||
OZ (call_proc_info->add_out_param(i,
|
||||
param_info->get_mode(),
|
||||
param_info->get_param_name(),
|
||||
pl_type,
|
||||
param_info->get_type_name(),
|
||||
OB_SYS_TENANT_ID == db_schema->get_tenant_id()
|
||||
? ObString("SYS") : db_schema->get_database_name_str()), i);
|
||||
}
|
||||
OZ (stmt->add_out_param(i,
|
||||
} else if (pl_type.is_user_type()) {
|
||||
// 通过Call语句执行PL且参数是复杂类型的情况, 仅在PS模式支持, 通过客户端无法构造复杂数据类型;
|
||||
// PS模式仅支持UDT作为出参, 这里将其他模式的复杂类型出参禁掉;
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_WARN("not supported other type as out parameter except udt", K(ret), K(pl_type.is_user_type()));
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "other complex type as out parameter except user define type");
|
||||
} else {
|
||||
OZ (call_proc_info->add_out_param(i,
|
||||
param_info->get_mode(),
|
||||
param_info->get_param_name(),
|
||||
pl_type,
|
||||
param_info->get_type_name(),
|
||||
OB_SYS_TENANT_ID == db_schema->get_tenant_id()
|
||||
? ObString("SYS") : db_schema->get_database_name_str()), i);
|
||||
ObString("")));
|
||||
}
|
||||
} else if (pl_type.is_user_type()) {
|
||||
// 通过Call语句执行PL且参数是复杂类型的情况, 仅在PS模式支持, 通过客户端无法构造复杂数据类型;
|
||||
// PS模式仅支持UDT作为出参, 这里将其他模式的复杂类型出参禁掉;
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_WARN("not supported other type as out parameter except udt", K(ret), K(pl_type.is_user_type()));
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "other complex type as out parameter except user define type");
|
||||
} else {
|
||||
OZ (stmt->add_out_param(i,
|
||||
param_info->get_mode(),
|
||||
param_info->get_param_name(),
|
||||
pl_type,
|
||||
param_info->get_type_name(),
|
||||
ObString("")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4: cg raw expr
|
||||
OX (call_proc_info->set_param_cnt(params.count()));
|
||||
OZ (call_proc_info->prepare_expression(params));
|
||||
OZ (call_proc_info->final_expression(params, session_info_, schema_checker_->get_schema_mgr()));
|
||||
OX (stmt->set_call_proc_info(call_proc_info));
|
||||
if (params_.is_execute_call_stmt_ && 0 != params_.cur_sql_.length()) {
|
||||
if (NULL != params_.param_list_) {
|
||||
OZ (call_proc_info->set_params_info(*params_.param_list_));
|
||||
}
|
||||
OZ (add_call_proc_info(call_proc_info));
|
||||
}
|
||||
CK (1 == call_proc_info->get_dependency_table().count());
|
||||
OZ (stmt->add_global_dependency_table(call_proc_info->get_dependency_table().at(0)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "lib/container/ob_se_array.h"
|
||||
#include "share/ob_rpc_struct.h"
|
||||
#include "share/schema/ob_schema_struct.h"
|
||||
#include "pl/pl_cache/ob_pl_cache.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -30,6 +31,7 @@ class ObRoutineInfo;
|
||||
namespace sql
|
||||
{
|
||||
class ObCallProcedureStmt;
|
||||
class ObCallProcedureInfo;
|
||||
class ObCallProcedureResolver: public ObCMDResolver
|
||||
{
|
||||
public:
|
||||
@ -40,7 +42,8 @@ public:
|
||||
private:
|
||||
int resolve_cparams(const ParseNode* params_node,
|
||||
const share::schema::ObRoutineInfo *routien_info,
|
||||
ObCallProcedureStmt *stmt);
|
||||
ObCallProcedureInfo *call_proc_info,
|
||||
ObIArray<ObRawExpr*> ¶ms);
|
||||
int resolve_cparam_without_assign(const ParseNode *param_node,
|
||||
const int64_t position,
|
||||
common::ObIArray<ObRawExpr*> ¶ms);
|
||||
@ -50,6 +53,9 @@ private:
|
||||
int resolve_param_exprs(const ParseNode *params_node,
|
||||
ObIArray<ObRawExpr*> &expr_params);
|
||||
int check_param_expr_legal(ObRawExpr *param);
|
||||
int find_call_proc_info(ObCallProcedureStmt &stmt);
|
||||
int add_call_proc_info(ObCallProcedureInfo *call_info);
|
||||
int generate_pl_cache_ctx(pl::ObPLCacheCtx &pc_ctx);
|
||||
private:
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObCallProcedureResolver);
|
||||
|
@ -21,89 +21,140 @@
|
||||
#include "ob_call_procedure_stmt.h"
|
||||
#include "pl/ob_pl_type.h"
|
||||
#include "sql/resolver/expr/ob_raw_expr_util.h"
|
||||
#include "sql/code_generator/ob_expr_generator_impl.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
|
||||
int ObCallProcedureStmt::deep_copy(ObIAllocator *allocator,
|
||||
const ObCallProcedureStmt *other)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (this != other) {
|
||||
CK (OB_NOT_NULL(other));
|
||||
CK (OB_NOT_NULL(allocator));
|
||||
OX (can_direct_use_param_ = other->can_direct_use_param_);
|
||||
OX (package_id_ = other->package_id_);
|
||||
OX (routine_id_ = other->routine_id_);
|
||||
OX (param_cnt_ = other->param_cnt_);
|
||||
OX (out_idx_ = other->out_idx_);
|
||||
CK (other->out_name_.count() == other->out_type_.count());
|
||||
CK (other->out_name_.count() == other->out_mode_.count());
|
||||
CK (other->out_name_.count() == other->out_type_name_.count());
|
||||
CK (other->out_name_.count() == other->out_type_owner_.count());
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < other->out_name_.count(); ++i) {
|
||||
ObString copy;
|
||||
pl::ObPLDataType pl_copy_type;
|
||||
OZ (ob_write_string(*allocator, other->out_name_.at(i), copy));
|
||||
OZ (out_name_.push_back(copy));
|
||||
OZ (ob_write_string(*allocator, other->out_type_name_.at(i), copy));
|
||||
OZ (out_type_name_.push_back(copy));
|
||||
OZ (ob_write_string(*allocator, other->out_type_owner_.at(i), copy));
|
||||
OZ (out_type_owner_.push_back(copy));
|
||||
OZ (pl_copy_type.deep_copy(*allocator, other->out_type_.at(i)));
|
||||
OZ (out_type_.push_back(pl_copy_type));
|
||||
OZ (out_mode_.push_back(other->out_mode_.at(i)));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < other->in_type_infos_.count(); ++i) {
|
||||
TypeInfo copy;
|
||||
OZ (copy.deep_copy(allocator, &(other->in_type_infos_.at(i))));
|
||||
OZ (in_type_infos_.push_back(copy));
|
||||
}
|
||||
OZ (ob_write_string(*allocator, other->db_name_, db_name_));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObCallProcedureStmt::add_out_param(
|
||||
int ObCallProcedureInfo::add_out_param(
|
||||
int64_t i, int64_t mode, const ObString &name,
|
||||
const pl::ObPLDataType &type,
|
||||
const ObString &out_type_name, const ObString &out_type_owner)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObString store_name;
|
||||
ObString store_out_type_name;
|
||||
ObString store_out_type_owner;
|
||||
pl::ObPLDataType pl_data_type;
|
||||
if (OB_FAIL(out_idx_.add_member(i))) {
|
||||
LOG_WARN("failed to add out index", K(i), K(name), K(type), K(ret));
|
||||
} else if (OB_FAIL(out_mode_.push_back(mode))) {
|
||||
LOG_WARN("failed to push mode", K(ret));
|
||||
} else if (OB_FAIL(out_name_.push_back(name))) {
|
||||
} else if (OB_FAIL(ob_write_string(allocator_, name, store_name))) {
|
||||
LOG_WARN("failed to deep copy name", K(ret), K(name));
|
||||
} else if (OB_FAIL(out_name_.push_back(store_name))) {
|
||||
LOG_WARN("push back error", K(i), K(name), K(type), K(ret));
|
||||
} else if (OB_FAIL(out_type_.push_back(type))) {
|
||||
} else if (OB_FAIL(pl_data_type.deep_copy(allocator_, type))) {
|
||||
LOG_WARN("fail to deep copy pl data type", K(type), K(ret));
|
||||
} else if (OB_FAIL(out_type_.push_back(pl_data_type))) {
|
||||
LOG_WARN("push back error", K(i), K(name), K(type), K(ret));
|
||||
} else if (OB_FAIL(out_type_name_.push_back(out_type_name))) {
|
||||
} else if (OB_FAIL(ob_write_string(allocator_, out_type_name, store_out_type_name))) {
|
||||
LOG_WARN("failed to deep copy name", K(ret), K(name));
|
||||
} else if (OB_FAIL(out_type_name_.push_back(store_out_type_name))) {
|
||||
LOG_WARN("push back error", K(i), K(name), K(type), K(out_type_name), K(ret));
|
||||
} else if (OB_FAIL(out_type_owner_.push_back(out_type_owner))) {
|
||||
} else if (OB_FAIL(ob_write_string(allocator_, out_type_owner, store_out_type_owner))) {
|
||||
LOG_WARN("failed to deep copy name", K(ret), K(name));
|
||||
} else if (OB_FAIL(out_type_owner_.push_back(store_out_type_owner))) {
|
||||
LOG_WARN("push back error", K(i), K(name), K(ret), K(out_type_name), K(out_type_owner), K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObCallProcedureStmt::add_params(const common::ObIArray<sql::ObRawExpr*>& params)
|
||||
int ObCallProcedureInfo::prepare_expression(const common::ObArray<sql::ObRawExpr*> params)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObArray<ObSqlExpression*> array;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < params.count(); ++i) {
|
||||
if (OB_ISNULL(params.at(i))) {
|
||||
ObSqlExpression *expr = NULL;
|
||||
if (OB_FAIL(sql_expression_factory_.alloc(expr))) {
|
||||
LOG_WARN("failed to alloc expr", K(ret));
|
||||
} else if (OB_ISNULL(expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("param at i is null", K(ret), K(i));
|
||||
} else if (OB_FAIL(params_.push_back(params.at(i)))) {
|
||||
LOG_WARN("failed to push back", K(ret), K(i));
|
||||
} else {
|
||||
param_cnt_++;
|
||||
}
|
||||
LOG_WARN("failed to create expr", K(ret));
|
||||
} else if (OB_FAIL(array.push_back(expr))) {
|
||||
LOG_WARN("push back error", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
|
||||
OZ (expressions_.assign(array));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObCallProcedureInfo::final_expression(const common::ObArray<sql::ObRawExpr*> params,
|
||||
ObSQLSessionInfo *session_info,
|
||||
share::schema::ObSchemaGetterGuard *schema_guard)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
// generate static engine expressions
|
||||
sql::ObRawExprUniqueSet raw_exprs(false);
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < params.count(); i++) {
|
||||
OZ(raw_exprs.append(params.at(i)));
|
||||
}
|
||||
sql::ObStaticEngineExprCG se_cg(allocator_,
|
||||
session_info,
|
||||
schema_guard,
|
||||
0 /* original param cnt */,
|
||||
0/* param count*/,
|
||||
GET_MIN_CLUSTER_VERSION());
|
||||
se_cg.set_rt_question_mark_eval(true);
|
||||
OZ(se_cg.generate(raw_exprs, frame_info_));
|
||||
|
||||
uint32_t expr_op_size = 0;
|
||||
RowDesc row_desc;
|
||||
ObExprGeneratorImpl expr_generator(expr_operator_factory_, 0, 0,
|
||||
&expr_op_size, row_desc);
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < params.count(); ++i) {
|
||||
ObRawExpr *raw_expr = params.at(i);
|
||||
ObSqlExpression *expression = static_cast<ObSqlExpression*>(expressions_.at(i));
|
||||
if (OB_ISNULL(raw_expr) || OB_ISNULL(expression)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("Invalid arguments", K(i), K(raw_expr), K(expression), K(ret));
|
||||
} else {
|
||||
if (OB_FAIL(expr_generator.generate(*raw_expr, *expression))) {
|
||||
SQL_LOG(WARN, "Generate post_expr error", K(ret), KPC(raw_expr));
|
||||
} else {
|
||||
expression->set_expr(raw_expr->rt_expr_);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
expr_op_size_ = std::max(frame_info_.need_ctx_cnt_, static_cast<int64_t>(expr_op_size));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObCallProcedureInfo::reset()
|
||||
{
|
||||
pl::ObPLCacheObject::reset();
|
||||
can_direct_use_param_ = false;
|
||||
package_id_ = common::OB_INVALID_ID;
|
||||
routine_id_ = common::OB_INVALID_ID;
|
||||
param_cnt_ = 0;
|
||||
is_udt_routine_ = false;
|
||||
}
|
||||
|
||||
int ObCallProcedureInfo::check_need_add_cache_obj_stat(ObILibCacheCtx &ctx, bool &need_real_add)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
//ObPLCacheCtx &pc_ctx = static_cast<ObPLCacheCtx&>(ctx);
|
||||
//need_real_add = pc_ctx.need_add_obj_stat_;
|
||||
need_real_add = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObCallProcedureInfo::dump_deleted_log_info(const bool is_debug_log /* = true */) const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,57 +27,38 @@
|
||||
#include "sql/parser/parse_node.h"
|
||||
#include "sql/resolver/cmd/ob_cmd_stmt.h"
|
||||
#include "sql/plan_cache/ob_prepare_stmt_struct.h"
|
||||
#include "pl/pl_cache/ob_pl_cache_object.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObCallProcedureStmt : public ObCMDStmt
|
||||
|
||||
class ObCallProcedureInfo : public pl::ObPLCacheObject
|
||||
{
|
||||
public:
|
||||
explicit ObCallProcedureStmt(common::ObIAllocator *name_pool)
|
||||
: ObCMDStmt(name_pool, stmt::T_CALL_PROCEDURE),
|
||||
explicit ObCallProcedureInfo(lib::MemoryContext &mem_context)
|
||||
: pl::ObPLCacheObject(ObLibCacheNameSpace::NS_CALLSTMT, mem_context),
|
||||
can_direct_use_param_(false),
|
||||
package_id_(common::OB_INVALID_ID),
|
||||
routine_id_(common::OB_INVALID_ID),
|
||||
param_cnt_(0),
|
||||
params_(),
|
||||
out_idx_(),
|
||||
out_mode_(),
|
||||
out_name_(),
|
||||
out_type_(),
|
||||
db_name_(),
|
||||
is_udt_routine_(false),
|
||||
expr_factory_(NULL) {
|
||||
is_udt_routine_(false) {
|
||||
}
|
||||
ObCallProcedureStmt()
|
||||
: ObCMDStmt(stmt::T_CALL_PROCEDURE),
|
||||
can_direct_use_param_(false),
|
||||
package_id_(common::OB_INVALID_ID),
|
||||
routine_id_(common::OB_INVALID_ID),
|
||||
param_cnt_(0),
|
||||
params_(),
|
||||
out_idx_(),
|
||||
out_mode_(),
|
||||
out_name_(),
|
||||
out_type_(),
|
||||
db_name_(),
|
||||
is_udt_routine_(false),
|
||||
expr_factory_(NULL) {}
|
||||
virtual ~ObCallProcedureStmt() {
|
||||
if (OB_NOT_NULL(expr_factory_)) {
|
||||
expr_factory_->~ObRawExprFactory();
|
||||
expr_factory_ = NULL;
|
||||
}
|
||||
|
||||
virtual ~ObCallProcedureInfo() {
|
||||
}
|
||||
|
||||
inline uint64_t get_package_id() const { return package_id_; }
|
||||
inline void set_package_id(const uint64_t package_id) { package_id_ = package_id; }
|
||||
inline uint64_t get_routine_id() const { return routine_id_; }
|
||||
inline void set_routine_id(const uint64_t routine_id) { routine_id_ = routine_id; }
|
||||
inline const common::ObIArray<sql::ObRawExpr*> &get_params() const { return params_; }
|
||||
inline common::ObIArray<sql::ObRawExpr*> &get_params() { return params_; }
|
||||
inline int add_param(sql::ObRawExpr* param) { return params_.push_back(param); }
|
||||
int add_params(const common::ObIArray<sql::ObRawExpr*>& params);
|
||||
|
||||
inline int64_t get_output_count() { return out_idx_.num_members(); }
|
||||
inline bool is_out_param(int64_t i) { return out_idx_.has_member(i); }
|
||||
inline ObBitSet<> &get_out_idx() { return out_idx_; }
|
||||
@ -95,7 +76,10 @@ public:
|
||||
const ParamTypeInfoArray& get_type_infos() const {
|
||||
return in_type_infos_;
|
||||
}
|
||||
inline void set_db_name(const ObString db_name) { db_name_ = db_name; }
|
||||
inline int set_db_name(const ObString db_name)
|
||||
{
|
||||
return ob_write_string(get_allocator(), db_name, db_name_);
|
||||
}
|
||||
const ObString& get_db_name() const { return db_name_; }
|
||||
|
||||
//int get_convert_size(int64_t &cv_size) const;
|
||||
@ -107,13 +91,20 @@ public:
|
||||
void set_is_udt_routine(bool v) { is_udt_routine_ = v; }
|
||||
bool is_udt_routine() const { return is_udt_routine_; }
|
||||
|
||||
int deep_copy(ObIAllocator *allocator, const ObCallProcedureStmt *other);
|
||||
int prepare_expression(const common::ObArray<sql::ObRawExpr*> params);
|
||||
int final_expression(const common::ObArray<sql::ObRawExpr*> params,
|
||||
ObSQLSessionInfo *session_info,
|
||||
share::schema::ObSchemaGetterGuard *schema_guard);
|
||||
|
||||
virtual void reset();
|
||||
virtual void dump_deleted_log_info(const bool is_debug_log = true) const;
|
||||
virtual int check_need_add_cache_obj_stat(ObILibCacheCtx &ctx, bool &need_real_add);
|
||||
|
||||
//virtual obrpc::ObDDLArg &get_ddl_arg() { return ddl_arg_; }
|
||||
TO_STRING_KV(K_(can_direct_use_param),
|
||||
K_(package_id),
|
||||
K_(routine_id),
|
||||
K_(params),
|
||||
//K_(params),
|
||||
K_(out_idx),
|
||||
K_(out_name),
|
||||
K_(out_type),
|
||||
@ -125,7 +116,6 @@ private:
|
||||
uint64_t package_id_;
|
||||
uint64_t routine_id_;
|
||||
int64_t param_cnt_;
|
||||
common::ObArray<sql::ObRawExpr*> params_;
|
||||
ObBitSet<> out_idx_;
|
||||
ObSEArray<int64_t, 32> out_mode_;
|
||||
ObSEArray<ObString, 32> out_name_;
|
||||
@ -135,11 +125,37 @@ private:
|
||||
ParamTypeInfoArray in_type_infos_;
|
||||
ObString db_name_;
|
||||
bool is_udt_routine_;
|
||||
ObRawExprFactory *expr_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ObCallProcedureInfo);
|
||||
};
|
||||
|
||||
class ObCallProcedureStmt : public ObCMDStmt
|
||||
{
|
||||
public:
|
||||
explicit ObCallProcedureStmt()
|
||||
: ObCMDStmt(NULL, stmt::T_CALL_PROCEDURE),
|
||||
call_proc_info_(NULL),
|
||||
cache_call_info_guard_(MAX_HANDLE) {
|
||||
}
|
||||
|
||||
virtual ~ObCallProcedureStmt() {
|
||||
call_proc_info_ = NULL;
|
||||
}
|
||||
|
||||
void set_call_proc_info(ObCallProcedureInfo *info) {
|
||||
call_proc_info_ = info;
|
||||
}
|
||||
ObCallProcedureInfo *get_call_proc_info() { return call_proc_info_; }
|
||||
ObCacheObjGuard &get_cacheobj_guard() { return cache_call_info_guard_; }
|
||||
|
||||
private:
|
||||
ObCallProcedureInfo *call_proc_info_;
|
||||
ObCacheObjGuard cache_call_info_guard_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ObCallProcedureStmt);
|
||||
};
|
||||
|
||||
|
||||
}//namespace sql
|
||||
}//namespace oceanbase
|
||||
|
||||
|
@ -347,7 +347,7 @@ int ObCreatePackageResolver::resolve_functions_spec(const ObPackageInfo &package
|
||||
routine_info.set_reads_sql_data();
|
||||
} else if (pl_routine_info->is_modifies_sql_data()) {
|
||||
routine_info.set_modifies_sql_data();
|
||||
} else {
|
||||
} else if (pl_routine_info->is_contains_sql()) {
|
||||
routine_info.set_contains_sql();
|
||||
}
|
||||
// udt type 相关信息设置
|
||||
@ -713,6 +713,32 @@ int ObCreatePackageBodyResolver::update_routine_route_sql(ObIAllocator &allocato
|
||||
OX (routine_info.set_route_sql(route_sql));
|
||||
OZ (ObSQLUtils::convert_sql_text_to_schema_for_storing(allocator, session_info.get_dtc_params(), routine_body));
|
||||
OX (routine_info.set_routine_body(routine_body));
|
||||
if (OB_SUCC(ret)) {
|
||||
if (pl_routine_info->is_modifies_sql_data()) {
|
||||
routine_info.set_modifies_sql_data();
|
||||
} else if (pl_routine_info->is_reads_sql_data()) {
|
||||
routine_info.set_reads_sql_data();
|
||||
} else if (pl_routine_info->is_contains_sql()) {
|
||||
routine_info.set_contains_sql();
|
||||
} else if (pl_routine_info->is_no_sql()) {
|
||||
routine_info.set_no_sql();
|
||||
}
|
||||
if (pl_routine_info->is_wps()) {
|
||||
routine_info.set_wps();
|
||||
}
|
||||
if (pl_routine_info->is_rps()) {
|
||||
routine_info.set_rps();
|
||||
}
|
||||
if (pl_routine_info->is_has_sequence()) {
|
||||
routine_info.set_has_sequence();
|
||||
}
|
||||
if (pl_routine_info->is_has_out_param()) {
|
||||
routine_info.set_has_out_param();
|
||||
}
|
||||
if (pl_routine_info->is_external_state()) {
|
||||
routine_info.set_external_state();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
OZ (public_routine_list.push_back(routine_info));
|
||||
|
@ -92,7 +92,7 @@ int ObCreateRoutineResolver::analyze_router_sql(obrpc::ObCreateRoutineArg *crt_r
|
||||
if (OB_SUCC(ret)) {
|
||||
pl::ObPLRouter router(routine_info, *session_info_, *schema_checker_->get_schema_guard(), *params_.sql_proxy_);
|
||||
ObString route_sql;
|
||||
if (OB_FAIL(router.analyze(route_sql, crt_routine_arg->dependency_infos_))) {
|
||||
if (OB_FAIL(router.analyze(route_sql, crt_routine_arg->dependency_infos_, routine_info))) {
|
||||
LOG_WARN("failed to analyze route sql", K(route_sql), K(ret));
|
||||
} else if (OB_FAIL(ObSQLUtils::convert_sql_text_to_schema_for_storing(
|
||||
*allocator_, session_info_->get_dtc_params(), route_sql))) {
|
||||
@ -514,6 +514,28 @@ int ObCreateRoutineResolver::resolve_param_type(const ParseNode *type_node,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObCreateRoutineResolver::analyze_expr_type(ObRawExpr *&expr,
|
||||
ObRoutineInfo &routine_info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
CK (OB_NOT_NULL(expr));
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (T_OP_GET_PACKAGE_VAR == expr->get_expr_type()) {
|
||||
OX (routine_info.set_rps());
|
||||
} else if (T_FUN_UDF == expr->get_expr_type()) {
|
||||
OX (routine_info.set_external_state());
|
||||
} else {
|
||||
for (int64_t i = 0;
|
||||
OB_SUCC(ret) &&
|
||||
(!routine_info.is_rps() || !routine_info.is_external_state()) &&
|
||||
i < expr->get_param_count();
|
||||
++i) {
|
||||
OZ (analyze_expr_type(expr->get_param_expr(i), routine_info));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObCreateRoutineResolver::resolve_param_list(const ParseNode *param_list, ObRoutineInfo &routine_info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -568,9 +590,11 @@ int ObCreateRoutineResolver::resolve_param_list(const ParseNode *param_list, ObR
|
||||
break;
|
||||
case MODE_OUT:
|
||||
routine_param.set_out_sp_param_flag();
|
||||
routine_info.set_has_out_param();
|
||||
break;
|
||||
case MODE_INOUT:
|
||||
routine_param.set_inout_sp_param_flag();
|
||||
routine_info.set_has_out_param();
|
||||
break;
|
||||
default:
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
@ -625,6 +649,7 @@ int ObCreateRoutineResolver::resolve_param_list(const ParseNode *param_list, ObR
|
||||
*allocator_, session_info_->get_dtc_params(), default_value));
|
||||
OZ (routine_param.set_default_value(default_value));
|
||||
OX (match_info.need_cast_ ? routine_param.set_default_cast() : void(NULL));
|
||||
OZ (analyze_expr_type(default_expr, routine_info));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ private:
|
||||
int resolve_sp_name(const ParseNode *parse_node, obrpc::ObCreateRoutineArg *crt_routine_arg);
|
||||
int resolve_sp_body(const ParseNode *parse_node, share::schema::ObRoutineInfo &routine_info);
|
||||
int resolve_ret_type(const ParseNode *ret_type_node, share::schema::ObRoutineInfo &func_info);
|
||||
int analyze_expr_type(ObRawExpr *&expr, share::schema::ObRoutineInfo &routine_info);
|
||||
int resolve_param_list(const ParseNode *param_list, share::schema::ObRoutineInfo &routine_info);
|
||||
int resolve_replace(const ParseNode *parse_node, obrpc::ObCreateRoutineArg *crt_routine_arg);
|
||||
int resolve_editionable(const ParseNode *parse_node, obrpc::ObCreateRoutineArg *crt_routine_arg);
|
||||
|
@ -1063,6 +1063,16 @@ int ObTriggerResolver::analyze_trigger(ObSchemaGetterGuard &schema_guard,
|
||||
&(package_spec_ast.get_body()->get_namespace()),
|
||||
package_body_ast,
|
||||
true));
|
||||
if (OB_SUCC(ret)) {
|
||||
uint64_t data_version = 0;
|
||||
if (OB_FAIL(GET_MIN_DATA_VERSION(trigger_info.get_tenant_id(), data_version))) {
|
||||
LOG_WARN("failed to get data version", K(ret));
|
||||
} else if (data_version < DATA_VERSION_4_2_0_0) {
|
||||
// do nothing
|
||||
} else {
|
||||
OX (const_cast<ObTriggerInfo&>(trigger_info).set_analyze_flag(package_body_ast.get_analyze_flag()));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && lib::is_oracle_mode()) {
|
||||
if (is_alter_compile) {
|
||||
OZ (ObPLCompiler::update_schema_object_dep_info(package_body_ast,
|
||||
|
@ -1733,6 +1733,67 @@ int ObDMLResolver::resolve_columns_field_list_first(ObRawExpr *&expr, ObArray<Ob
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int check_is_pl_jsontype(const oceanbase::pl::ObUserDefinedType *user_type)
|
||||
{
|
||||
INIT_SUCC(ret);
|
||||
|
||||
if (OB_ISNULL(user_type)) {
|
||||
} else if (user_type->get_type() == oceanbase::pl::PL_OPAQUE_TYPE) {
|
||||
if (user_type->get_name().compare("JSON_OBJECT_T") == 0
|
||||
|| user_type->get_name().compare("JSON_ELEMENT_T") == 0) {
|
||||
ret = OB_ERR_PL_JSONTYPE_USAGE;
|
||||
LOG_WARN("invalid pl json type userage in pl/sql", K(ret),
|
||||
K(user_type->get_type()), K(user_type->get_user_type_id()));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObDMLResolver::generate_pl_data_type(ObRawExpr *expr, pl::ObPLDataType &pl_data_type)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
CK (OB_NOT_NULL(expr));
|
||||
CK (OB_NOT_NULL(params_.secondary_namespace_));
|
||||
CK (expr->get_result_type().is_valid());
|
||||
if (OB_SUCC(ret)) {
|
||||
pl::ObPLDataType final_type;
|
||||
// T_OBJ_ACCESS_REF expr, access obj type (not user defined type)
|
||||
bool access_obj_type = false;
|
||||
if (expr->is_obj_access_expr()) {
|
||||
// T_OBJ_ACCESS_REF return ObExtendType for object access for writing, get obj type
|
||||
// from %final_type;
|
||||
// see comment in ObPLInto::add_into
|
||||
const auto &access_expr = static_cast<const ObObjAccessRawExpr &>(*expr);
|
||||
OZ(access_expr.get_final_type(final_type));
|
||||
OX(access_obj_type = !final_type.is_user_type());
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (expr->get_result_type().is_ext() && !access_obj_type) {
|
||||
CK (expr->is_obj_access_expr());
|
||||
OX (pl_data_type = final_type);
|
||||
if (OB_SUCC(ret) && NULL != params_.secondary_namespace_) {
|
||||
const pl::ObUserDefinedType *user_type = NULL;
|
||||
OZ (params_.secondary_namespace_->get_pl_data_type_by_id(final_type.get_user_type_id(), user_type));
|
||||
OZ (check_is_pl_jsontype(user_type));
|
||||
}
|
||||
} else {
|
||||
ObDataType type;
|
||||
if (access_obj_type) {
|
||||
type.set_meta_type(final_type.get_data_type()->get_meta_type());
|
||||
type.set_accuracy(final_type.get_data_type()->get_accuracy());
|
||||
} else {
|
||||
type.set_meta_type(expr->get_result_type().get_obj_meta());
|
||||
type.set_accuracy(expr->get_result_type().get_accuracy());
|
||||
}
|
||||
OX (pl_data_type.set_data_type(type));
|
||||
OX (pl_data_type.set_type(PL_OBJ_TYPE));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObDMLResolver::resolve_into_variables(const ParseNode *node,
|
||||
ObIArray<ObString> &user_vars,
|
||||
ObIArray<ObRawExpr*> &pl_vars,
|
||||
@ -1818,43 +1879,6 @@ int ObDMLResolver::resolve_into_variables(const ParseNode *node,
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_WARN("dynamic sql returning bulk collect is not supported!", K(ret));
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "dynamic sql returning bulk collect");
|
||||
} else { //非BULK
|
||||
for (uint64_t i = 0; OB_SUCC(ret) && i < pl_vars.count(); ++i) {
|
||||
CK (OB_NOT_NULL(pl_vars.at(i)));
|
||||
if (OB_SUCC(ret) && pl_vars.at(i)->is_obj_access_expr()) {
|
||||
pl::ObPLDataType pl_type;
|
||||
const ObUserDefinedType *user_type = NULL;
|
||||
const ObRecordType *record_type = NULL;
|
||||
ObObjAccessRawExpr* access_expr = static_cast<ObObjAccessRawExpr*>(pl_vars.at(i));
|
||||
OZ (access_expr->get_final_type(pl_type));
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (pl_type.is_collection_type()) {
|
||||
if (pl_type.is_udt_type()) {
|
||||
ret = OB_ERR_INVALID_TYPE_FOR_OP;
|
||||
LOG_WARN("inconsistent datatypes", K(ret), K(pl_type));
|
||||
} else {
|
||||
ret = OB_ERR_LOCAL_COLL_IN_SQL;
|
||||
LOG_WARN("local collection types not allowed in SQL statements",
|
||||
K(ret), K(pl_type));
|
||||
}
|
||||
} else if (pl_type.is_record_type()) {
|
||||
CK (OB_NOT_NULL(params_.secondary_namespace_));
|
||||
OZ (params_.secondary_namespace_->get_pl_data_type_by_id(pl_type.get_user_type_id(),
|
||||
user_type));
|
||||
CK (OB_NOT_NULL(user_type));
|
||||
CK (user_type->is_record_type());
|
||||
CK (OB_NOT_NULL(record_type = static_cast<const ObRecordType*>(user_type)));
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < record_type->get_record_member_count(); ++i) {
|
||||
const ObPLDataType *member = record_type->get_record_member_type(i);
|
||||
CK (OB_NOT_NULL(member));
|
||||
if (OB_SUCC(ret) && !member->is_obj_type()) {
|
||||
ret = OB_ERR_INTO_EXPR_ILLEGAL;
|
||||
LOG_WARN("PLS-00597: expression 'string' in the INTO list is of wrong type", K(ret), K(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && !pl_vars.empty() && !user_vars.empty()) {
|
||||
@ -1884,6 +1908,301 @@ int ObDMLResolver::resolve_into_variables(const ParseNode *node,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (!user_vars.empty()) {
|
||||
// into user var in mysql mode
|
||||
CK (OB_NOT_NULL(select_stmt));
|
||||
if (OB_SUCC(ret) && NULL != params_.secondary_namespace_ &&
|
||||
select_stmt->get_select_items().count() != user_vars.count()) {
|
||||
ret = OB_ERR_COLUMN_SIZE;
|
||||
LOG_WARN("The used SELECT statements have a different number of columns", K(ret));
|
||||
}
|
||||
} else if (1 == node->value_) { // bulk into
|
||||
bool has_type_record_type = false;
|
||||
const ObPLDataType *into_var_type = NULL;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && !has_type_record_type && i < pl_vars.count(); ++i) {
|
||||
CK (OB_NOT_NULL(pl_vars.at(i)));
|
||||
if (OB_SUCC(ret) && pl_vars.at(i)->is_obj_access_expr()) {
|
||||
pl::ObPLDataType pl_type;
|
||||
const ObUserDefinedType *user_type = NULL;
|
||||
ObObjAccessRawExpr* access_expr = static_cast<ObObjAccessRawExpr*>(pl_vars.at(i));
|
||||
OZ (access_expr->get_final_type(pl_type));
|
||||
CK (pl_type.is_collection_type());
|
||||
CK (OB_NOT_NULL(params_.secondary_namespace_));
|
||||
OZ (params_.secondary_namespace_->get_pl_data_type_by_id(pl_type.get_user_type_id(),
|
||||
user_type));
|
||||
CK (OB_NOT_NULL(user_type));
|
||||
if (OB_SUCC(ret)) {
|
||||
const ObCollectionType *coll_type = static_cast<const ObCollectionType*>(user_type);
|
||||
CK (OB_NOT_NULL(coll_type));
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (coll_type->get_element_type().is_type_record()) {
|
||||
has_type_record_type = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (has_type_record_type && pl_vars.count() != 1) {
|
||||
ret = OB_ERR_MULTI_RECORD;
|
||||
LOG_WARN("coercion into multiple record targets not supported", K(ret));
|
||||
}
|
||||
/* 走到这里如果没报错,有两种可能:
|
||||
1.into 变量中, 元素成员是type record的nested table变量只有唯一一个.
|
||||
2.into 变量中, 没有元素成员是type record的nested table变量 */
|
||||
if (OB_SUCC(ret)) {
|
||||
pl::ObPLDataType pl_type;
|
||||
const ObUserDefinedType *into_user_type = NULL;
|
||||
const ObUserDefinedType *elem_user_type = NULL;
|
||||
const ObRecordType *into_record_type = NULL;
|
||||
int64_t value_expr_count = 0;
|
||||
int64_t into_data_type_count = 0;
|
||||
bool is_compatible = true;
|
||||
bool skip_comp = false;
|
||||
if (has_type_record_type) {
|
||||
ObObjAccessRawExpr* access_expr = NULL;
|
||||
const ObCollectionType *coll_type = NULL;
|
||||
CK (1 == pl_vars.count());
|
||||
OX (access_expr = static_cast<ObObjAccessRawExpr*>(pl_vars.at(0)));
|
||||
OZ (access_expr->get_final_type(pl_type));
|
||||
OZ (params_.secondary_namespace_->get_pl_data_type_by_id(pl_type.get_user_type_id(), into_user_type));
|
||||
CK (OB_NOT_NULL(into_user_type));
|
||||
OX (coll_type = static_cast<const ObCollectionType*>(into_user_type));
|
||||
CK (OB_NOT_NULL(coll_type));
|
||||
CK (coll_type->get_element_type().is_record_type());
|
||||
OZ (params_.secondary_namespace_->get_pl_data_type_by_id(coll_type->get_element_type().get_user_type_id(), elem_user_type));
|
||||
CK (OB_NOT_NULL(elem_user_type));
|
||||
OX (into_record_type = static_cast<const ObRecordType*>(elem_user_type));
|
||||
OX (into_data_type_count = into_record_type->get_record_member_count());
|
||||
} else {
|
||||
into_data_type_count = pl_vars.count();
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (NULL != select_stmt) { // select into
|
||||
ObIArray<SelectItem> &select_items = select_stmt->get_select_items();
|
||||
value_expr_count = select_items.count();
|
||||
} else {
|
||||
ObDelUpdStmt *del_up_stmt = static_cast<ObDelUpdStmt*>(get_basic_stmt());
|
||||
CK (OB_NOT_NULL(del_up_stmt));
|
||||
OX (value_expr_count = del_up_stmt->get_returning_exprs().count());
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (value_expr_count > into_data_type_count) {
|
||||
ret = OB_ERR_NOT_ENOUGH_VALUES;
|
||||
LOG_WARN("type not compatible", K(ret));
|
||||
} else if (value_expr_count < into_data_type_count) {
|
||||
ret = OB_ERR_TOO_MANY_VALUES;
|
||||
LOG_WARN("type not compatible", K(ret));
|
||||
}
|
||||
CK(OB_NOT_NULL(params_.session_info_));
|
||||
for (int64_t i = 0; OB_SUCC(ret) && is_compatible && i < into_data_type_count; ++i) {
|
||||
ObRawExpr *value_expr = NULL;
|
||||
if (NULL != select_stmt) {
|
||||
value_expr = select_stmt->get_select_items().at(i).expr_;
|
||||
} else {
|
||||
value_expr = static_cast<ObDelUpdStmt*>(get_basic_stmt())->get_returning_exprs().at(i);
|
||||
}
|
||||
pl::ObPLDataType into_pl_type;
|
||||
if (OB_ISNULL(value_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("expr of select item is null", K(ret));
|
||||
} else if (OB_FAIL(value_expr->formalize(params_.session_info_))) {
|
||||
LOG_WARN("formailize column reference expr failed", K(ret));
|
||||
} else {
|
||||
if (has_type_record_type) {
|
||||
CK (OB_NOT_NULL(into_record_type));
|
||||
CK (OB_NOT_NULL(into_record_type->get_record_member_type(i)));
|
||||
OX (into_pl_type = *(into_record_type->get_record_member_type(i)));
|
||||
} else if (pl_vars.at(i)->get_expr_type() == T_QUESTIONMARK) {
|
||||
skip_comp = true;
|
||||
} else if (!pl_vars.at(i)->is_obj_access_expr()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("into variable need obj access", K(ret));
|
||||
} else {
|
||||
pl::ObPLDataType pl_type;
|
||||
const ObUserDefinedType *into_user_type = NULL;
|
||||
const ObCollectionType *coll_type = NULL;
|
||||
const ObUserDefinedType *elem_user_type = NULL;
|
||||
ObObjAccessRawExpr* access_expr = static_cast<ObObjAccessRawExpr*>(pl_vars.at(i));
|
||||
OZ (access_expr->get_final_type(pl_type));
|
||||
OZ (params_.secondary_namespace_->get_pl_data_type_by_id(pl_type.get_user_type_id(), into_user_type));
|
||||
CK (OB_NOT_NULL(into_user_type));
|
||||
OX (coll_type = static_cast<const ObCollectionType*>(into_user_type));
|
||||
CK (OB_NOT_NULL(coll_type));
|
||||
OX (into_pl_type = coll_type->get_element_type());
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && !skip_comp) {
|
||||
if (value_expr->get_data_type() != ObExtendType && into_pl_type.is_obj_type()) {
|
||||
CK (OB_NOT_NULL(into_pl_type.get_data_type()));
|
||||
OX (is_compatible = cast_supported(value_expr->get_data_type(),
|
||||
value_expr->get_collation_type(),
|
||||
into_pl_type.get_data_type()->get_obj_type(),
|
||||
into_pl_type.get_data_type()->get_collation_type()));
|
||||
} else if (value_expr->get_data_type() == ObExtendType &&
|
||||
(!into_pl_type.is_obj_type() ||
|
||||
(into_pl_type.get_data_type() != NULL && into_pl_type.get_data_type()->get_meta_type().is_ext()))) {
|
||||
uint64_t left_udt_id = value_expr->get_udt_id();
|
||||
uint64_t right_udt_id = (NULL == into_pl_type.get_data_type()) ? into_pl_type.get_user_type_id()
|
||||
: into_pl_type.get_data_type()->get_udt_id();
|
||||
if (left_udt_id != right_udt_id) {
|
||||
is_compatible = false;
|
||||
} else {
|
||||
// same composite type, compatible is true, do nothing.
|
||||
}
|
||||
} else {
|
||||
is_compatible = false;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && !is_compatible) {
|
||||
if (into_pl_type.is_udt_type()) {
|
||||
ret = OB_ERR_INVALID_TYPE_FOR_OP;
|
||||
LOG_WARN("inconsistent datatypes", K(ret), K(into_pl_type));
|
||||
} else {
|
||||
ret = OB_ERR_LOCAL_COLL_IN_SQL;
|
||||
LOG_WARN("local collection types not allowed in SQL statements",
|
||||
K(ret), K(pl_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // into
|
||||
bool has_type_record_type = false;
|
||||
const ObPLDataType *into_var_type = NULL;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && !has_type_record_type && i < pl_vars.count(); ++i) {
|
||||
CK (OB_NOT_NULL(pl_vars.at(i)));
|
||||
if (OB_SUCC(ret) && pl_vars.at(i)->is_obj_access_expr()) {
|
||||
pl::ObPLDataType pl_type;
|
||||
ObObjAccessRawExpr* access_expr = static_cast<ObObjAccessRawExpr*>(pl_vars.at(i));
|
||||
OZ (access_expr->get_final_type(pl_type));
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (pl_type.is_type_record()) {
|
||||
has_type_record_type = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (has_type_record_type && pl_vars.count() != 1) {
|
||||
ret = OB_ERR_MULTI_RECORD;
|
||||
LOG_WARN("coercion into multiple record targets not supported", K(ret));
|
||||
}
|
||||
|
||||
/* 走到这里如果没报错,有两种可能:
|
||||
1.into变量只有唯一一个type record.
|
||||
2.into变量无type record */
|
||||
if (OB_SUCC(ret)) {
|
||||
pl::ObPLDataType pl_type;
|
||||
const ObUserDefinedType *into_user_type = NULL;
|
||||
const ObRecordType *into_record_type = NULL;
|
||||
int64_t value_expr_count = 0;
|
||||
int64_t into_data_type_count = 0;
|
||||
bool is_compatible = true;
|
||||
bool skip_comp = false;
|
||||
if (has_type_record_type) {
|
||||
ObObjAccessRawExpr* access_expr = NULL;
|
||||
const pl::ObPLDataType *element_type = NULL;
|
||||
CK (1 == pl_vars.count());
|
||||
OX (access_expr = static_cast<ObObjAccessRawExpr*>(pl_vars.at(0)));
|
||||
OZ (access_expr->get_final_type(pl_type));
|
||||
OZ (params_.secondary_namespace_->get_pl_data_type_by_id(pl_type.get_user_type_id(), into_user_type));
|
||||
CK (OB_NOT_NULL(into_user_type));
|
||||
CK (into_user_type->is_record_type());
|
||||
OX (into_record_type = static_cast<const ObRecordType*>(into_user_type));
|
||||
OX (into_data_type_count = into_record_type->get_record_member_count());
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < into_data_type_count; ++i) {
|
||||
element_type = into_record_type->get_record_member_type(i);
|
||||
CK (OB_NOT_NULL(element_type));
|
||||
if (OB_SUCC(ret) && element_type->is_type_record()) {
|
||||
ret = OB_ERR_INTO_EXPR_ILLEGAL;
|
||||
LOG_WARN("inconsistent datatypes", K(ret));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
into_data_type_count = pl_vars.count();
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (NULL != select_stmt) { // select into
|
||||
ObIArray<SelectItem> &select_items = select_stmt->get_select_items();
|
||||
value_expr_count = select_items.count();
|
||||
} else {
|
||||
ObDelUpdStmt *del_up_stmt = static_cast<ObDelUpdStmt*>(get_basic_stmt());
|
||||
CK (OB_NOT_NULL(del_up_stmt));
|
||||
OX (value_expr_count = del_up_stmt->get_returning_exprs().count());
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (value_expr_count > into_data_type_count) {
|
||||
ret = OB_ERR_NOT_ENOUGH_VALUES;
|
||||
LOG_WARN("type not compatible", K(ret));
|
||||
} else if (value_expr_count < into_data_type_count) {
|
||||
ret = OB_ERR_TOO_MANY_VALUES;
|
||||
LOG_WARN("type not compatible", K(ret));
|
||||
}
|
||||
CK(OB_NOT_NULL(params_.session_info_));
|
||||
for (int64_t i = 0; OB_SUCC(ret) && is_compatible && i < into_data_type_count; ++i) {
|
||||
ObRawExpr *value_expr = NULL;
|
||||
if (NULL != select_stmt) {
|
||||
value_expr = select_stmt->get_select_items().at(i).expr_;
|
||||
} else {
|
||||
value_expr = static_cast<ObDelUpdStmt*>(get_basic_stmt())->get_returning_exprs().at(i);
|
||||
}
|
||||
pl::ObPLDataType into_pl_type;
|
||||
if (OB_ISNULL(value_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("expr of select item is null", K(ret));
|
||||
} else if (OB_FAIL(value_expr->formalize(params_.session_info_))) {
|
||||
LOG_WARN("formailize column reference expr failed", K(ret));
|
||||
} else {
|
||||
if (has_type_record_type) {
|
||||
CK (OB_NOT_NULL(into_record_type));
|
||||
CK (OB_NOT_NULL(into_record_type->get_record_member_type(i)));
|
||||
OX (into_pl_type = *(into_record_type->get_record_member_type(i)));
|
||||
} else if (pl_vars.at(i)->get_expr_type() == T_QUESTIONMARK) {
|
||||
skip_comp = true;
|
||||
} else {
|
||||
OZ (generate_pl_data_type(pl_vars.at(i), into_pl_type));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && !skip_comp) {
|
||||
if (value_expr->get_data_type() != ObExtendType && into_pl_type.is_obj_type()) {
|
||||
CK (OB_NOT_NULL(into_pl_type.get_data_type()));
|
||||
OX (is_compatible = cast_supported(value_expr->get_data_type(),
|
||||
value_expr->get_collation_type(),
|
||||
into_pl_type.get_data_type()->get_obj_type(),
|
||||
into_pl_type.get_data_type()->get_collation_type()));
|
||||
} else if (value_expr->get_data_type() == ObExtendType &&
|
||||
(!into_pl_type.is_obj_type() ||
|
||||
(into_pl_type.get_data_type() != NULL && into_pl_type.get_data_type()->get_meta_type().is_ext()))) {
|
||||
uint64_t left_udt_id = value_expr->get_udt_id();
|
||||
uint64_t right_udt_id = (NULL == into_pl_type.get_data_type()) ? into_pl_type.get_user_type_id()
|
||||
: into_pl_type.get_data_type()->get_udt_id();
|
||||
if (left_udt_id != right_udt_id) {
|
||||
is_compatible = false;
|
||||
} else {
|
||||
// same composite type, compatible is true, do nothing.
|
||||
}
|
||||
} else {
|
||||
is_compatible = false;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && !is_compatible) {
|
||||
if (into_pl_type.is_udt_type()) {
|
||||
ret = OB_ERR_INVALID_TYPE_FOR_OP;
|
||||
LOG_WARN("inconsistent datatypes", K(ret), K(into_pl_type));
|
||||
} else {
|
||||
ret = OB_ERR_LOCAL_COLL_IN_SQL;
|
||||
LOG_WARN("local collection types not allowed in SQL statements",
|
||||
K(ret), K(pl_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && NULL != select_stmt) {
|
||||
ObIArray<SelectItem> &select_items = select_stmt->get_select_items();
|
||||
CK(OB_NOT_NULL(params_.session_info_));
|
||||
@ -2189,14 +2508,19 @@ int ObDMLResolver::resolve_qualified_identifier(ObQualifiedName &q_name,
|
||||
ret = OB_ERR_PRIVATE_UDF_USE_IN_SQL;
|
||||
LOG_WARN("function 'string' may not be used in SQL", K(ret), KPC(udf));
|
||||
} else {
|
||||
stmt_->get_query_ctx()->has_pl_udf_ = true;
|
||||
OX (stmt_->get_query_ctx()->disable_udf_parallel_ |= !udf->is_parallel_enable());
|
||||
}
|
||||
} else if (T_FUN_PL_COLLECTION_CONSTRUCT == real_ref_expr->get_expr_type()) {
|
||||
if (!params_.is_resolve_table_function_expr_) {
|
||||
//such as insert into tbl values(1,3, coll('a', 1));
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_WARN("dml with collection or record construction function is not supported", K(ret));
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "dml with collection or record construction function is");
|
||||
if ((NULL == params_.secondary_namespace_ && NULL == session_info_->get_pl_context()) ||
|
||||
(current_scope_ != T_FIELD_LIST_SCOPE && current_scope_ != T_INTO_SCOPE)) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_WARN("dml with collection or record construction function is not supported", K(ret));
|
||||
LOG_USER_ERROR(OB_NOT_SUPPORTED, "dml with collection or record construction function is");
|
||||
} else {
|
||||
is_external = false;
|
||||
}
|
||||
} else {
|
||||
is_external = false;
|
||||
}
|
||||
@ -2282,7 +2606,10 @@ int ObDMLResolver::resolve_qualified_identifier(ObQualifiedName &q_name,
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && OB_NOT_NULL(real_ref_expr) && real_ref_expr->is_udf_expr()) {
|
||||
stmt_->get_query_ctx()->has_pl_udf_ = true;
|
||||
ObUDFRawExpr *udf = static_cast<ObUDFRawExpr *>(real_ref_expr);
|
||||
if (OB_NOT_NULL(udf)) {
|
||||
OX (stmt_->get_query_ctx()->disable_udf_parallel_ |= !udf->is_parallel_enable());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4123,6 +4450,7 @@ int ObDMLResolver::resolve_function_table_item(const ParseNode &parse_tree,
|
||||
OZ (stmt->add_global_dependency_table(table_version));
|
||||
OZ (stmt->add_ref_obj_version(dep_obj_id, dep_db_id, ObObjectType::VIEW, table_version, *allocator_));
|
||||
}
|
||||
OX (stmt_->get_query_ctx()->disable_udf_parallel_ |= !udf->is_parallel_enable());
|
||||
} else if (OB_SUCC(ret) && function_table_expr->is_sys_func_expr()) {
|
||||
// xxx
|
||||
}
|
||||
@ -10167,6 +10495,7 @@ int ObDMLResolver::resolve_external_name(ObQualifiedName &q_name,
|
||||
//the flag will change to false;
|
||||
OX (expr->set_is_called_in_sql(true));
|
||||
}
|
||||
OX (stmt_->get_query_ctx()->disable_udf_parallel_ |= !udf_expr->is_parallel_enable());
|
||||
} else if (T_FUN_PL_OBJECT_CONSTRUCT == expr->get_expr_type()) {
|
||||
ObDMLStmt *stmt = get_stmt();
|
||||
ObObjectConstructRawExpr *object_expr = static_cast<ObObjectConstructRawExpr*>(expr);
|
||||
|
@ -303,6 +303,7 @@ public:
|
||||
const ObIArray<uint64_t> &db_ids);
|
||||
ObDMLStmt *get_stmt();
|
||||
protected:
|
||||
int generate_pl_data_type(ObRawExpr *expr, pl::ObPLDataType &pl_data_type);
|
||||
int resolve_into_variables(const ParseNode *node,
|
||||
ObIArray<ObString> &user_vars,
|
||||
ObIArray<ObRawExpr*> &pl_vars,
|
||||
|
@ -385,7 +385,8 @@ ObDMLStmt::ObDMLStmt(stmt::StmtType type)
|
||||
user_var_exprs_(),
|
||||
check_constraint_items_(),
|
||||
dblink_id_(OB_INVALID_ID),
|
||||
is_reverse_link_(false)
|
||||
is_reverse_link_(false),
|
||||
is_bulk_(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -495,6 +496,7 @@ int ObDMLStmt::assign(const ObDMLStmt &other)
|
||||
transpose_item_ = other.transpose_item_;
|
||||
dblink_id_ = other.dblink_id_;
|
||||
is_reverse_link_ = other.is_reverse_link_;
|
||||
is_bulk_ = other.is_bulk_;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -657,6 +659,7 @@ int ObDMLStmt::deep_copy_stmt_struct(ObIAllocator &allocator,
|
||||
is_fetch_with_ties_ = other.is_fetch_with_ties_;
|
||||
dblink_id_ = other.dblink_id_;
|
||||
is_reverse_link_ = other.is_reverse_link_;
|
||||
is_bulk_ = other.is_bulk_;
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
TransposeItem *tmp = NULL;
|
||||
|
@ -973,6 +973,8 @@ public:
|
||||
inline bool is_dblink_stmt() const { return OB_INVALID_ID != dblink_id_; }
|
||||
inline void set_reverse_link() { is_reverse_link_ = true; }
|
||||
inline bool is_reverse_link() const { return is_reverse_link_; }
|
||||
inline void set_bulk() { is_bulk_ = true; }
|
||||
inline bool is_bulk() const { return is_bulk_; }
|
||||
int add_subquery_ref(ObQueryRefRawExpr *query_ref);
|
||||
virtual int get_child_stmt_size(int64_t &child_size) const;
|
||||
int64_t get_subquery_expr_size() const { return subquery_exprs_.count(); }
|
||||
@ -1210,6 +1212,7 @@ protected:
|
||||
*/
|
||||
int64_t dblink_id_;
|
||||
bool is_reverse_link_;
|
||||
bool is_bulk_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -59,6 +59,7 @@ class ObPLCodeGenerator;
|
||||
namespace sql
|
||||
{
|
||||
class ObStmt;
|
||||
class ObCallProcedureInfo;
|
||||
class ObSQLSessionInfo;
|
||||
class ObExprOperator;
|
||||
class ObRawExprFactory;
|
||||
@ -1607,6 +1608,7 @@ public:
|
||||
friend sql::ObExpr *ObStaticEngineExprCG::get_rt_expr(const ObRawExpr &raw_expr);
|
||||
friend sql::ObExpr *ObExprOperator::get_rt_expr(const ObRawExpr &raw_expr) const;
|
||||
friend class pl::ObPLCodeGenerator;
|
||||
friend class sql::ObCallProcedureInfo;
|
||||
friend class sql::ObRTDatumArith;
|
||||
|
||||
explicit ObRawExpr(ObItemType expr_type = T_INVALID)
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "sql/plan_cache/ob_plan_cache_util.h"
|
||||
#include "sql/plan_cache/ob_plan_cache_struct.h"
|
||||
#include "objit/common/ob_item_type.h"
|
||||
#include "sql/plan_cache/ob_cache_object_factory.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
|
@ -280,6 +280,7 @@ public:
|
||||
const ParseNode *node,
|
||||
ObQualifiedName &q_name,
|
||||
const ObSQLSessionInfo &session_info);
|
||||
|
||||
static int resolve_external_symbol(common::ObIAllocator &allocator,
|
||||
sql::ObRawExprFactory &expr_factory,
|
||||
sql::ObSQLSessionInfo &session_info,
|
||||
|
@ -89,6 +89,7 @@ ObBasicSessionInfo::ObBasicSessionInfo()
|
||||
name_pool_(ObModIds::OB_SQL_SESSION, OB_MALLOC_NORMAL_BLOCK_SIZE),
|
||||
trans_flags_(),
|
||||
sql_scope_flags_(),
|
||||
need_reset_package_(false),
|
||||
base_sys_var_alloc_(ObModIds::OB_SQL_SESSION, OB_MALLOC_NORMAL_BLOCK_SIZE),
|
||||
inc_sys_var_alloc1_(ObModIds::OB_SQL_SESSION, OB_MALLOC_NORMAL_BLOCK_SIZE),
|
||||
inc_sys_var_alloc2_(ObModIds::OB_SQL_SESSION, OB_MALLOC_NORMAL_BLOCK_SIZE),
|
||||
@ -144,6 +145,7 @@ ObBasicSessionInfo::ObBasicSessionInfo()
|
||||
thread_id_(0),
|
||||
is_password_expired_(false),
|
||||
process_query_time_(0)
|
||||
|
||||
{
|
||||
thread_data_.reset();
|
||||
MEMSET(sys_vars_, 0, sizeof(sys_vars_));
|
||||
@ -334,6 +336,7 @@ void ObBasicSessionInfo::reset(bool skip_sys_var)
|
||||
package_info_allocator_.reset();
|
||||
trans_flags_.reset();
|
||||
sql_scope_flags_.reset();
|
||||
need_reset_package_ = false;
|
||||
//bucket_allocator_wrapper_.reset();
|
||||
user_var_val_map_.reuse();
|
||||
if (!skip_sys_var) {
|
||||
@ -4759,6 +4762,25 @@ int ObBasicSessionInfo::track_user_var(const common::ObString &user_var)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObBasicSessionInfo::remove_changed_user_var(const common::ObString &user_var)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (user_var.empty()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid input value", K(user_var), K(ret));
|
||||
} else {
|
||||
bool found = false;
|
||||
for (int64_t i = 0; !found && OB_SUCC(ret) && i < changed_user_vars_.count(); ++i) {
|
||||
if (changed_user_vars_.at(i) == user_var) {
|
||||
OZ (changed_user_vars_.remove(i));
|
||||
OX (found = true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObBasicSessionInfo::is_sys_var_actully_changed(const ObSysVarClassType &sys_var_id,
|
||||
const ObObj &old_val,
|
||||
ObObj &new_val,
|
||||
|
@ -945,6 +945,8 @@ public:
|
||||
const ObSessionVariable *get_user_variable(const common::ObString &var) const;
|
||||
const common::ObObj *get_user_variable_value(const common::ObString &var) const;
|
||||
bool user_variable_exists(const common::ObString &var) const;
|
||||
inline void set_need_reset_package(bool need_reset) { need_reset_package_ = need_reset; }
|
||||
bool need_reset_package() { return need_reset_package_; }
|
||||
/// @}
|
||||
|
||||
inline static ObDataTypeCastParams create_dtc_params(const ObBasicSessionInfo *session_info)
|
||||
@ -1029,6 +1031,7 @@ public:
|
||||
int add_changed_user_var(const common::ObString &name, common::ObIArray<common::ObString> &array);
|
||||
int track_sys_var(const share::ObSysVarClassType &sys_var_id, const common::ObObj &old_val);
|
||||
int track_user_var(const common::ObString &user_var);
|
||||
int remove_changed_user_var(const common::ObString &user_var);
|
||||
int is_sys_var_actully_changed(const share::ObSysVarClassType &sys_var_id,
|
||||
const common::ObObj &old_val,
|
||||
common::ObObj &new_val,
|
||||
@ -1936,6 +1939,7 @@ protected:
|
||||
common::ObStringBuf name_pool_; // for variables names and statement names
|
||||
TransFlags trans_flags_;
|
||||
SqlScopeFlags sql_scope_flags_;
|
||||
bool need_reset_package_; // for dbms_session.reset_package
|
||||
|
||||
private:
|
||||
common::ObStringBuf base_sys_var_alloc_; // for variables names and statement names
|
||||
|
@ -1723,6 +1723,57 @@ void ObSQLSessionInfo::reset_all_package_state()
|
||||
}
|
||||
}
|
||||
|
||||
int ObSQLSessionInfo::reset_all_package_state_by_dbms_session(bool need_set_sync_var)
|
||||
{
|
||||
/* its called by dbms_session.reset_package()
|
||||
* in this mode
|
||||
* 1. we also should reset all user variable mocked by package var
|
||||
* 2. if the package is a trigger, we should do nothing
|
||||
*
|
||||
*/
|
||||
int ret = OB_SUCCESS;
|
||||
if (0 == package_state_map_.size()
|
||||
|| NULL != get_pl_context()
|
||||
|| false == need_reset_package()) {
|
||||
// do nothing
|
||||
} else {
|
||||
ObSEArray<int64_t, 4> remove_packages;
|
||||
if (0 != package_state_map_.size()) {
|
||||
FOREACH(it, package_state_map_) {
|
||||
if (!share::schema::ObTriggerInfo::is_trigger_package_id(it->second->get_package_id())) {
|
||||
ret = ret != OB_SUCCESS ? ret : remove_packages.push_back(it->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < remove_packages.count(); ++i) {
|
||||
ObPLPackageState *package_state = NULL;
|
||||
bool need_reset = false;
|
||||
OZ (package_state_map_.get_refactored(remove_packages.at(i), package_state));
|
||||
CK (OB_NOT_NULL(package_state));
|
||||
OZ (package_state_map_.erase_refactored(remove_packages.at(i)));
|
||||
OX (need_reset = true);
|
||||
OZ (package_state->remove_user_variables_for_package_state(*this));
|
||||
if (need_reset && NULL != package_state) {
|
||||
package_state->reset(this);
|
||||
package_state->~ObPLPackageState();
|
||||
get_package_allocator().free(package_state);
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && need_set_sync_var) {
|
||||
ObSessionVariable sess_var;
|
||||
ObString key("##__OB_RESET_ALL_PACKAGE_BY_DBMS_SESSION_RESET_PACKAGE__");
|
||||
sess_var.meta_.set_timestamp();
|
||||
sess_var.value_.set_timestamp(ObTimeUtility::current_time());
|
||||
if (OB_FAIL(ObBasicSessionInfo::replace_user_variable(key, sess_var))) {
|
||||
LOG_WARN("add user var failed", K(ret));
|
||||
}
|
||||
}
|
||||
// wether reset succ or not, set need_reset_package to false
|
||||
set_need_reset_package(false);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObSQLSessionInfo::reset_all_serially_package_state()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -1832,7 +1883,13 @@ int ObSQLSessionInfo::replace_user_variable(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_package_variable && OB_NOT_NULL(get_pl_engine())) {
|
||||
if (0 == name.case_compare("##__OB_RESET_ALL_PACKAGE_BY_DBMS_SESSION_RESET_PACKAGE__")) {
|
||||
// "##__OB_RESET_ALL_PACKAGE_BY_DBMS_SESSION_RESET_PACKAGE__"
|
||||
// this variable is used to reset_package.
|
||||
// if we get a set stmt of OB_RESET_ALL_PACKAGE_BY_DBMS_SESSION_RESET_PACKAGE
|
||||
// we should only reset_all_package, do not need set_user_variable
|
||||
OZ (reset_all_package_state_by_dbms_session(false));
|
||||
} else if (is_package_variable && OB_NOT_NULL(get_pl_engine())) {
|
||||
OZ (set_package_variable(ctx, name, value.value_, true));
|
||||
} else {
|
||||
OZ (ObBasicSessionInfo::replace_user_variable(name, value));
|
||||
|
@ -828,6 +828,7 @@ public:
|
||||
void reset_pl_debugger_resource();
|
||||
void reset_all_package_changed_info();
|
||||
void reset_all_package_state();
|
||||
int reset_all_package_state_by_dbms_session(bool need_set_sync_var);
|
||||
int reset_all_serially_package_state();
|
||||
bool is_package_state_changed() const;
|
||||
bool get_changed_package_state_num() const;
|
||||
|
@ -81,11 +81,11 @@ begin
|
||||
select x from dual;
|
||||
end//
|
||||
call p(1);
|
||||
+---+
|
||||
| x |
|
||||
+---+
|
||||
| 1 |
|
||||
+---+
|
||||
+------+
|
||||
| x |
|
||||
+------+
|
||||
| 1 |
|
||||
+------+
|
||||
select * from a;
|
||||
+------+------+------+
|
||||
| a1 | a2 | a3 |
|
||||
|
@ -1316,7 +1316,8 @@ Procedure sql_mode Create Procedure character_set_client collation_connection Da
|
||||
opp CREATE DEFINER = admin@% PROCEDURE `test`.`opp`
|
||||
(
|
||||
IN `n` bigint(20) unsigned, OUT `pp` tinyint(1)
|
||||
) begin
|
||||
)
|
||||
READS SQL DATA begin
|
||||
declare r double;
|
||||
declare b, s bigint unsigned default 0;
|
||||
set r = sqrt(n);
|
||||
@ -1372,6 +1373,7 @@ bar CREATE DEFINER = admin@% PROCEDURE `test`.`bar`
|
||||
(
|
||||
IN `x` char(16), IN `y` int(11)
|
||||
)
|
||||
MODIFIES SQL DATA
|
||||
COMMENT `111111111111`
|
||||
insert into test.t1 values (x, y) utf8mb4 utf8mb4_general_ci utf8mb4_general_ci
|
||||
show procedure status like 'bar'|
|
||||
@ -2241,6 +2243,7 @@ Procedure sql_mode Create Procedure character_set_client collation_connection Da
|
||||
bug2564_1 CREATE DEFINER = admin@% PROCEDURE `test`.`bug2564_1`
|
||||
()
|
||||
|
||||
MODIFIES SQL DATA
|
||||
COMMENT `Joe's procedure`
|
||||
insert into `t1` values ("foo", 1) utf8mb4 utf8mb4_general_ci utf8mb4_general_ci
|
||||
show create procedure bug2564_2|
|
||||
@ -4589,8 +4592,8 @@ use test|
|
||||
select schema_name from information_schema.schemata where
|
||||
schema_name like 'bug18344%'|
|
||||
schema_name
|
||||
bug18344_012345678901
|
||||
bug18344_0123456789012
|
||||
bug18344_012345678901
|
||||
select routine_name,routine_schema from information_schema.routines where
|
||||
routine_schema like 'bug18344%'|
|
||||
routine_name routine_schema
|
||||
@ -6116,7 +6119,8 @@ show create procedure proc_25411_a;
|
||||
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
|
||||
proc_25411_a CREATE DEFINER = admin@% PROCEDURE `test`.`proc_25411_a`
|
||||
()
|
||||
begin
|
||||
|
||||
READS SQL DATA begin
|
||||
/* real comment */
|
||||
select 1;
|
||||
/*! select 2; */
|
||||
@ -6140,7 +6144,8 @@ Procedure sql_mode Create Procedure character_set_client collation_connection Da
|
||||
proc_25411_b CREATE DEFINER = admin@% PROCEDURE `test`.`proc_25411_b`
|
||||
(
|
||||
IN `p1` int(11), IN `p2` int(11), IN `p3` int(11)
|
||||
) begin
|
||||
)
|
||||
READS SQL DATA begin
|
||||
select p1, p2;
|
||||
end utf8mb4 utf8mb4_general_ci utf8mb4_general_ci
|
||||
select name, param_list, body from mysql.proc where name like "%25411%";
|
||||
@ -6169,7 +6174,8 @@ show create procedure proc_25411_c;
|
||||
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
|
||||
proc_25411_c CREATE DEFINER = admin@% PROCEDURE `test`.`proc_25411_c`
|
||||
()
|
||||
begin
|
||||
|
||||
READS SQL DATA begin
|
||||
select 1/*!,2*//*!00000,3*//*!99999,4*/;
|
||||
select 1/*! ,2*//*!00000 ,3*//*!99999 ,4*/;
|
||||
select 1/*!,2 *//*!00000,3 *//*!99999,4 */;
|
||||
@ -6197,7 +6203,8 @@ show create procedure proc_26302;
|
||||
Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
|
||||
proc_26302 CREATE DEFINER = admin@% PROCEDURE `test`.`proc_26302`
|
||||
()
|
||||
select 1 /* testing */ utf8mb4 utf8mb4_general_ci utf8mb4_general_ci
|
||||
|
||||
READS SQL DATA select 1 /* testing */ utf8mb4 utf8mb4_general_ci utf8mb4_general_ci
|
||||
select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES
|
||||
where ROUTINE_NAME = "proc_26302";
|
||||
ROUTINE_NAME ROUTINE_DEFINITION
|
||||
|
Loading…
x
Reference in New Issue
Block a user