2
* Copyright (c) 2021 OceanBase
3
* OceanBase CE is licensed under Mulan PubL v2.
4
* You can use this software according to the terms and conditions of the Mulan PubL v2.
5
* You may obtain a copy of Mulan PubL v2 at:
6
* http://license.coscl.org.cn/MulanPubL-2.0
7
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
8
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
9
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
10
* See the Mulan PubL v2 for more details.
13
#define USING_LOG_PREFIX PL
15
#include "pl/ob_pl_package.h"
16
#include "pl/ob_pl_exception_handling.h"
17
#include "lib/oblog/ob_log_module.h"
18
#include "share/schema/ob_package_info.h"
19
#include "sql/engine/ob_exec_context.h"
20
#include "sql/plan_cache/ob_cache_object_factory.h"
24
using namespace common;
26
using namespace share::schema;
31
int ObPLPackageAST::init(const ObString &db_name,
32
const ObString &package_name,
33
ObPackageType package_type,
36
int64_t package_version,
37
ObPLPackageAST *parent_package_ast)
40
const ObPLUserTypeTable *parent_user_type_table = NULL;
41
ObPLRoutineTable *parent_routine_table = NULL;
42
ObPLConditionTable *parent_condition_table = NULL;
46
database_id_ = database_id;
47
package_type_ = package_type;
48
version_ = package_version;
49
if (OB_NOT_NULL(parent_package_ast)) {
50
compile_flag_ = parent_package_ast->get_compile_flag();
51
serially_reusable_ = parent_package_ast->get_serially_reusable();
52
parent_user_type_table = &parent_package_ast->get_user_type_table();
53
parent_routine_table = &parent_package_ast->get_routine_table();
54
parent_condition_table = &parent_package_ast->get_condition_table();
56
if (OB_NOT_NULL(parent_user_type_table)) {
57
user_type_table_.set_type_start_gen_id(parent_user_type_table->get_type_start_gen_id());
59
if (OB_FAIL(routine_table_.init(parent_routine_table))) {
60
LOG_WARN("routine info table init failed", K(ret));
62
if (OB_NOT_NULL(parent_condition_table)) {
63
OZ (condition_table_.init(*parent_condition_table));
67
&& parent_package_ast != NULL
68
&& !ObTriggerInfo::is_trigger_package_id(package_id)
69
&& PL_PACKAGE_BODY == package_type) {
70
ObSchemaObjVersion obj_version;
71
obj_version.object_id_ = parent_package_ast->get_id();
72
obj_version.version_ = parent_package_ast->get_version();
73
obj_version.object_type_ = DEPENDENCY_PACKAGE;
74
if (OB_FAIL(add_dependency_object(obj_version))) {
75
LOG_WARN("add dependency table failed", K(ret));
80
ObSchemaObjVersion obj_version;
81
if (ObTriggerInfo::is_trigger_package_id(package_id)) {
82
obj_version.object_id_ = ObTriggerInfo::get_package_trigger_id(package_id);
83
obj_version.object_type_ = DEPENDENCY_TRIGGER;
84
} else if (PL_UDT_OBJECT_SPEC == package_type || PL_UDT_OBJECT_BODY == package_type) {
85
obj_version.object_id_ = package_id;
86
obj_version.object_type_
87
= PL_UDT_OBJECT_SPEC == package_type ? DEPENDENCY_TYPE : DEPENDENCY_TYPE_BODY;
89
obj_version.object_id_ = package_id;
90
obj_version.object_type_ = (PL_PACKAGE_SPEC == package_type) ? DEPENDENCY_PACKAGE : DEPENDENCY_PACKAGE_BODY;
92
obj_version.version_ = package_version;
93
if (OB_FAIL(add_dependency_object(obj_version))) {
94
LOG_WARN("add dependency table failed", K(ret));
103
int ObPLPackageAST::process_generic_type()
105
int ret = OB_SUCCESS;
106
static const char *generic_type_table[PL_GENERIC_MAX] = {
121
" SYS$BULK_ERROR_RECORD",
125
if (0 == get_name().case_compare("STANDARD")
126
&& 0 == get_db_name().case_compare(OB_SYS_DATABASE_NAME)) {
127
const ObPLUserTypeTable &user_type_table = get_user_type_table();
128
const ObUserDefinedType *user_type = NULL;
129
for (int64_t i = 0; OB_SUCC(ret) && i < user_type_table.get_count(); ++i) {
130
if (OB_NOT_NULL(user_type = user_type_table.get_type(i))) {
131
for (int64_t j = 0; OB_SUCC(ret) && j < PL_GENERIC_MAX; ++j) {
132
if (0 == user_type->get_name().case_compare(generic_type_table[j])) {
133
(const_cast<ObUserDefinedType *>(user_type))
134
->set_generic_type(static_cast<ObPLGenericType>(j));
143
ObPLPackage::~ObPLPackage()
145
for (int64_t i = 0; i < var_table_.count(); ++i) {
146
if (OB_NOT_NULL(var_table_.at(i))) {
147
var_table_.at(i)->~ObPLVar();
150
for (int64_t i = 0; i < type_table_.count(); ++i) {
151
if (OB_NOT_NULL(type_table_.at(i))) {
152
type_table_.at(i)->~ObUserDefinedType();
157
int ObPLPackage::init(const ObPLPackageAST &package_ast)
159
int ret = OB_SUCCESS;
160
database_id_ = package_ast.get_database_id();
161
id_ = package_ast.get_id();
162
version_ = package_ast.get_version();
163
package_type_ = package_ast.get_package_type();
164
serially_reusable_ = package_ast.get_serially_reusable();
165
if (OB_FAIL(ob_write_string(get_allocator(), const_cast<ObString &>(package_ast.get_db_name()), db_name_))) {
166
LOG_WARN("copy db name failed", "db name", package_ast.get_db_name(), K(ret));
167
} else if (OB_FAIL(ob_write_string(get_allocator(), const_cast<ObString &>(package_ast.get_name()), name_))) {
168
LOG_WARN("copy package name failed", "package name", package_ast.get_name(), K(ret));
175
int ObPLPackage::instantiate_package_state(const ObPLResolveCtx &resolve_ctx,
176
ObExecContext &exec_ctx,
177
ObPLPackageState &package_state)
179
int ret = OB_SUCCESS;
182
ARRAY_FOREACH(var_table_, var_idx) {
183
const ObPLVar *var = var_table_.at(var_idx);
184
const ObPLDataType &var_type = var->get_type();
185
const ObObj *ser_value = NULL;
186
bool need_deserialize = false;
189
if (OB_ISNULL(var)) {
190
ret = OB_ERR_UNEXPECTED;
191
LOG_WARN("variable is null", K(ret), KPC(var), K(var_idx));
192
} else if (var_type.is_cursor_type()
193
&& OB_FAIL(resolve_ctx.session_info_.init_cursor_cache())) {
194
LOG_WARN("failed to init cursor cache", K(ret));
195
} else if (package_state.get_serially_reusable()) {
197
} else if (OB_FAIL(package_state.make_pkg_var_kv_key(resolve_ctx.allocator_, var_idx, VARIABLE, key))) {
198
LOG_WARN("make package var name failed", K(ret));
199
} else if (OB_NOT_NULL(ser_value = resolve_ctx.session_info_.get_user_variable_value(key))) {
200
need_deserialize = true;
203
} else if (OB_FAIL(var_type.init_session_var(resolve_ctx,
204
var_type.is_cursor_type() ?
205
package_state.get_pkg_cursor_allocator()
206
: package_state.get_pkg_allocator(),
208
(var->is_formal_param() || need_deserialize) ? NULL : get_default_expr(var->get_default()),
209
var->is_default_construct(),
211
LOG_WARN("init sesssion var failed", K(ret));
212
} else if (value.is_null_oracle() && var_type.is_not_null()) {
213
ret = OB_ERR_NUMERIC_OR_VALUE_ERROR;
214
LOG_WARN("cannot assign null to var with not null attribution", K(ret));
215
} else if (need_deserialize) {
216
if (var_type.is_cursor_type()) {
217
OV (ser_value->is_tinyint() || ser_value->is_number(),
218
OB_ERR_UNEXPECTED, KPC(ser_value), K(lbt()));
220
&& ser_value->is_tinyint() ? ser_value->get_bool() : !ser_value->is_zero_number()) {
221
ObPLCursorInfo *cursor = reinterpret_cast<ObPLCursorInfo *>(value.get_ext());
222
CK (OB_NOT_NULL(cursor));
223
OX (cursor->set_sync_cursor());
225
} else if (var_type.is_opaque_type()) {
226
if (ser_value->is_null()) {
227
ret = OB_NOT_SUPPORTED;
228
LOG_WARN("can not sync package opaque type", K(ret));
229
LOG_USER_ERROR(OB_NOT_SUPPORTED, "sync package opaque type");
232
// sync other server modify for this server! (from porxy or distribute plan)
233
OZ (var_type.deserialize(resolve_ctx,
234
var_type.is_cursor_type() ?
235
package_state.get_pkg_cursor_allocator()
236
: package_state.get_pkg_allocator(),
237
ser_value->get_hex_string().ptr(),
238
ser_value->get_hex_string().length(),
241
// record sync variable, avoid to sync tiwce!
242
if (OB_NOT_NULL(resolve_ctx.session_info_.get_pl_sync_pkg_vars())) {
243
OZ (resolve_ctx.session_info_.get_pl_sync_pkg_vars()->set_refactored(key));
246
//NOTE: do not remove package user variable! distribute plan will sync it to remote if needed!
247
OZ (package_state.add_package_var_val(value, var_type.get_type()));
249
if (OB_SUCC(ret) && !resolve_ctx.is_sync_package_var_) {
250
if (OB_FAIL(execute_init_routine(resolve_ctx.allocator_, exec_ctx))) {
251
LOG_WARN("execute init routine failed", K(ret));
257
int ObPLPackage::execute_init_routine(ObIAllocator &allocator, ObExecContext &exec_ctx)
260
int ret = OB_SUCCESS;
261
ObPLFunction *init_routine = routine_table_.at(ObPLRoutineTable::INIT_ROUTINE_IDX);
262
if (OB_NOT_NULL(init_routine)) {
263
pl::ObPL *pl_engine = NULL;
264
CK (OB_NOT_NULL(exec_ctx.get_my_session()));
265
CK (OB_NOT_NULL(pl_engine = exec_ctx.get_my_session()->get_pl_engine()));
269
ObSEArray<int64_t, 2> nocopy_param;
272
ObSEArray<int64_t, 2> subp_path;
273
OZ (pl_engine->execute(exec_ctx,
274
exec_ctx.get_allocator(),
275
init_routine->get_package_id(),
276
init_routine->get_routine_id(),
283
init_routine->is_function()));
286
LOG_DEBUG("package init routine function is null",
287
K(init_routine), K(get_name()), K(get_db_name()),
288
K(get_id()), K(get_version()), K(get_package_type()));
294
int ObPLPackage::add_var(ObPLVar *var)
296
int ret = OB_SUCCESS;
297
if (OB_FAIL(var_table_.push_back(var))) {
298
LOG_WARN("add symbol table failed", K(ret));
303
int ObPLPackage::get_var(const ObString &var_name, const ObPLVar *&var, int64_t &var_idx) const
305
int ret = OB_SUCCESS;
307
var_idx = OB_INVALID_INDEX;
308
for (int64_t i = 0; OB_ISNULL(var) && i < var_table_.count(); ++i) {
309
ObPLVar *tmp_var = var_table_.at(i);
310
if (!tmp_var->is_formal_param()
311
&& ObCharset::case_insensitive_equal(var_name, tmp_var->get_name())) {
312
if (tmp_var->is_dup_declare()) {
313
ret = OB_ERR_DECL_MORE_THAN_ONCE;
314
LOG_WARN("package var dup", K(ret), K(var_idx));
315
LOG_USER_ERROR(OB_ERR_DECL_MORE_THAN_ONCE, tmp_var->get_name().length(), tmp_var->get_name().ptr());
325
int ObPLPackage::get_var(int64_t var_idx, const ObPLVar *&var) const
327
int ret = OB_SUCCESS;
329
if (var_idx < 0 || var_idx >= var_table_.count()) {
330
LOG_WARN("var index invalid", K(var_idx), K(ret));
332
var = var_table_.at(var_idx);
337
int ObPLPackage::add_condition(ObPLCondition *value)
339
int ret = OB_SUCCESS;
340
OZ (condition_table_.push_back(value));
344
int ObPLPackage::get_condition(const ObString &condition_name, const ObPLCondition *&value)
346
int ret = OB_SUCCESS;
348
for (int64_t i = 0; OB_SUCC(ret) && i < condition_table_.count(); ++i) {
349
const ObPLCondition *tmp = condition_table_.at(i);
350
if (OB_ISNULL(tmp)) {
351
ret = OB_ERR_UNEXPECTED;
352
LOG_WARN("condition is null", K(ret), K(tmp));
353
} else if (ObCharset::case_insensitive_equal(condition_name, tmp->get_name())) {
361
int ObPLPackage::get_cursor(int64_t cursor_idx, const ObPLCursor *&cursor) const
363
int ret = OB_SUCCESS;
365
if (cursor_table_.get_count() > cursor_idx && cursor_idx >= 0) {
366
cursor = cursor_table_.get_cursor(cursor_idx);
367
CK (OB_NOT_NULL(cursor));
372
int ObPLPackage::get_cursor(
373
int64_t package_id, int64_t routine_id, int64_t index, const ObPLCursor *&cursor) const
375
int ret = OB_SUCCESS;
377
for (int64_t i = 0; OB_SUCC(ret) && i < cursor_table_.get_count(); ++i) {
378
const ObPLCursor *it = cursor_table_.get_cursor(i);
379
CK (OB_NOT_NULL(it));
380
if (it->get_package_id() == package_id
381
&& it->get_routine_id() == routine_id
382
&& it->get_index() == index) {
390
int ObPLPackage::get_cursor(
391
const ObString &cursor_name, const ObPLCursor *&cursor, int64_t &cursor_idx) const
393
int ret = OB_SUCCESS;
395
cursor_idx = OB_INVALID_INDEX;
396
for (int64_t i = 0; OB_SUCC(ret) && i < cursor_table_.get_count(); ++i) {
397
const ObPLCursor *it = cursor_table_.get_cursor(i);
398
const ObPLVar *v = NULL;
399
CK (OB_NOT_NULL(it));
400
CK (OB_NOT_NULL(v = get_var_table().at(it->get_index())));
401
if (OB_SUCC(ret) && 0 == v->get_name().case_compare(cursor_name)) {
410
int ObPLPackage::add_type(ObUserDefinedType *type)
412
int ret = OB_SUCCESS;
413
if (OB_FAIL(type_table_.push_back(type))) {
414
LOG_WARN("add user type table failed", K(ret));
419
int ObPLPackage::get_type(const common::ObString type_name, const ObUserDefinedType *&type) const
421
int ret = OB_SUCCESS;
423
for (int64_t i = 0; OB_SUCC(ret) && i < type_table_.count(); ++i) {
424
const ObUserDefinedType *tmp_type = type_table_.at(i);
425
if (ObCharset::case_insensitive_equal(type_name, tmp_type->get_name())) {
426
if (OB_NOT_NULL(type)) {
427
ret = OB_ERR_DECL_MORE_THAN_ONCE;
428
LOG_USER_ERROR(OB_ERR_DECL_MORE_THAN_ONCE, type_name.length(), type_name.ptr());
437
int ObPLPackage::get_type(uint64_t type_id, const ObUserDefinedType *&type) const
439
int ret = OB_SUCCESS;
441
if (OB_INVALID_ID == type_id) {
442
LOG_WARN("type id invalid", K(type_id), K(ret));
444
for (int64_t i = 0; OB_ISNULL(type) && i < type_table_.count(); ++i) {
445
const ObUserDefinedType *tmp_type = type_table_.at(i);
446
if (OB_ISNULL(tmp_type)) {
447
ret = OB_ERR_UNEXPECTED;
448
LOG_WARN("user type invalid", K(type_id), K(ret));
450
if (tmp_type->get_user_type_id() == type_id) {
459
} // end namespace oceanbase