[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:
obdev 2023-04-27 16:08:10 +08:00 committed by ob-robot
parent 8e9c9d0c5f
commit 57f1c6e7ee
92 changed files with 3534 additions and 1304 deletions

View File

@ -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

View File

@ -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 &params)
{
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;

View File

@ -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 &params);
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);
};

View File

@ -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 &current_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))) {

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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_; }

View File

@ -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);

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -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, &not_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, &not_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);
}
}
}

View File

@ -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;
};
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
};

View File

@ -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;

View File

@ -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;

View 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 &params)
{
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;
}
}
}

View 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 &params);
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

View File

@ -305,6 +305,27 @@ int ObDBMSSession::set_identifier(sql::ObExecContext &ctx,
return ret;
}
int ObDBMSSession::reset_package(sql::ObExecContext &ctx,
sql::ParamStore &params,
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)

View File

@ -34,6 +34,8 @@ public:
sql::ObExecContext &ctx, sql::ParamStore &params, common::ObObj &result);
static int set_identifier(
sql::ObExecContext &ctx, sql::ParamStore &params, common::ObObj &result);
static int reset_package(
sql::ObExecContext &ctx, sql::ParamStore &params, common::ObObj &result);
private:
static int check_argument(const ObObj &input_param, bool allow_null,
bool need_case_up, int32_t param_idx,

View File

@ -175,8 +175,17 @@ int ObDbmsInfo::set_bind_param(const ObString &param_name, const ObObjParam&para
}
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 &param_name, const ObObjParam&para
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;
}
}

View File

@ -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 都会被重置

View File

@ -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.

View File

@ -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'.

View File

@ -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));

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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),
],
)

View File

@ -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;
};
};

View File

@ -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); }

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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; }

View File

@ -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;
}

View File

@ -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;
};
};
};

View File

@ -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;
}

View File

@ -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;

View File

@ -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() ||

View File

@ -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));
}

View File

@ -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;

View File

@ -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;

View File

@ -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++) {

View File

@ -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);

View File

@ -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();
}
}
}

View File

@ -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;

View File

@ -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();
}
}
}

View File

@ -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;

View File

@ -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();
}
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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 &current_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,

View File

@ -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;

View File

@ -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_;

View File

@ -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));

View File

@ -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;

View File

@ -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_;

View File

@ -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

View File

@ -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_

View File

@ -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) {

View File

@ -129,6 +129,7 @@ enum CacheRefHandleID
PLAN_BASELINE_HANDLE,
TABLEAPI_NODE_HANDLE,
SQL_PLAN_HANDLE,
CALLSTMT_HANDLE,
MAX_HANDLE
};

View File

@ -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;

View File

@ -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*> &params)
{
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;
}

View File

@ -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*> &params);
int resolve_cparam_without_assign(const ParseNode *param_node,
const int64_t position,
common::ObIArray<ObRawExpr*> &params);
@ -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);

View File

@ -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
{
}
}
}

View File

@ -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

View File

@ -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));

View File

@ -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));
}
}
}

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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>

View File

@ -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)

View File

@ -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
{

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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));

View File

@ -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;

View File

@ -81,11 +81,11 @@ begin
select x from dual;
end//
call p(1);
+---+
| x |
+---+
| 1 |
+---+
+------+
| x |
+------+
| 1 |
+------+
select * from a;
+------+------+------+
| a1 | a2 | a3 |

View File

@ -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