oceanbase

Форк
0
/
ob_pl_package.cpp 
459 строк · 15.7 Кб
1
/**
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.
11
 */
12

13
#define USING_LOG_PREFIX PL
14

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"
21

22
namespace oceanbase
23
{
24
using namespace common;
25
using namespace sql;
26
using namespace share::schema;
27

28
namespace pl
29
{
30

31
int ObPLPackageAST::init(const ObString &db_name,
32
                         const ObString &package_name,
33
                         ObPackageType package_type,
34
                         uint64_t database_id,
35
                         uint64_t package_id,
36
                         int64_t package_version,
37
                         ObPLPackageAST *parent_package_ast)
38
{
39
  int ret = OB_SUCCESS;
40
  const ObPLUserTypeTable *parent_user_type_table = NULL;
41
  ObPLRoutineTable *parent_routine_table = NULL;
42
  ObPLConditionTable *parent_condition_table = NULL;
43
  db_name_ = db_name;
44
  name_ = package_name;
45
  id_ = package_id;
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();
55
  }
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());
58
  }
59
  if (OB_FAIL(routine_table_.init(parent_routine_table))) {
60
    LOG_WARN("routine info table init failed", K(ret));
61
  }
62
  if (OB_NOT_NULL(parent_condition_table)) {
63
    OZ (condition_table_.init(*parent_condition_table));
64
  }
65

66
  if (OB_SUCC(ret)
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));
76
    }
77
  }
78

79
  if (OB_SUCC(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;
88
    } else {
89
      obj_version.object_id_ = package_id;
90
      obj_version.object_type_ = (PL_PACKAGE_SPEC == package_type) ? DEPENDENCY_PACKAGE : DEPENDENCY_PACKAGE_BODY;
91
    }
92
    obj_version.version_ = package_version;
93
    if (OB_FAIL(add_dependency_object(obj_version))) {
94
      LOG_WARN("add dependency table failed", K(ret));
95
    }
96
  }
97
  if (OB_SUCC(ret)) {
98
    inited_ = true;
99
  }
100
  return ret;
101
}
102

103
int ObPLPackageAST::process_generic_type()
104
{
105
  int ret = OB_SUCCESS;
106
  static const char *generic_type_table[PL_GENERIC_MAX] = {
107
    "", // INVALID
108

109
    "<ADT_1>",
110
    "<RECORD_1>",
111
    "<TUPLE_1>",
112
    "<VARRAY_1>",
113
    "<V2_TABLE_1>",
114
    "<TABLE_1>",
115
    "<COLLECTION_1>",
116
    "<REF_CURSOR_1>",
117

118
    "<TYPED_TABLE>",
119
    "<ADT_WITH_OID>",
120
    " SYS$INT_V2TABLE",
121
    " SYS$BULK_ERROR_RECORD",
122
    " SYS$REC_V2TABLE",
123
    "<ASSOC_ARRAY_1>"
124
  };
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));
135
          }
136
        }
137
      }
138
    }
139
  }
140
  return ret;
141
}
142

143
ObPLPackage::~ObPLPackage()
144
{
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();
148
    }
149
  }
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();
153
    }
154
  }
155
}
156

157
int ObPLPackage::init(const ObPLPackageAST &package_ast)
158
{
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));
169
  } else {
170
    inited_ = true;
171
  }
172
  return ret;
173
}
174

175
int ObPLPackage::instantiate_package_state(const ObPLResolveCtx &resolve_ctx,
176
                                           ObExecContext &exec_ctx,
177
                                           ObPLPackageState &package_state)
178
{
179
  int ret = OB_SUCCESS;
180
  ObString key;
181
  ObObj value;
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;
187
    key.reset();
188
    value.reset();
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()) {
196
      // do nothing ...
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;
201
    }
202
    if (OB_FAIL(ret)) {
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(),
207
                                                 exec_ctx,
208
                                                 (var->is_formal_param() || need_deserialize) ? NULL : get_default_expr(var->get_default()),
209
                                                 var->is_default_construct(),
210
                                                 value))) {
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()));
219
        if (OB_SUCC(ret)
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());
224
        }
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");
230
        }
231
      } else {
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(),
239
                                value));
240
      }
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));
244
      }
245
    }
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()));
248
  }
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));
252
    }
253
  }
254
  return ret;
255
}
256

257
int ObPLPackage::execute_init_routine(ObIAllocator &allocator, ObExecContext &exec_ctx)
258
{
259
  UNUSED(allocator);
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()));
266

267
    if (OB_SUCC(ret)) {
268
      ParamStore params;
269
      ObSEArray<int64_t, 2> nocopy_param;
270
      ObObj result;
271
      int status;
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(),
277
                             subp_path,
278
                             params,
279
                             nocopy_param,
280
                             result,
281
                             &status,
282
                             false,
283
                             init_routine->is_function()));
284
    }
285
  } else {
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()));
289
  }
290
  return ret;
291
}
292

293

294
int ObPLPackage::add_var(ObPLVar *var)
295
{
296
  int ret = OB_SUCCESS;
297
  if (OB_FAIL(var_table_.push_back(var))) {
298
    LOG_WARN("add symbol table failed", K(ret));
299
  }
300
  return ret;
301
}
302

303
int ObPLPackage::get_var(const ObString &var_name, const ObPLVar *&var, int64_t &var_idx) const
304
{
305
  int ret = OB_SUCCESS;
306
  var = NULL;
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());
316
      } else {
317
        var = tmp_var;
318
        var_idx = i;
319
      }
320
    }
321
  }
322
  return ret;
323
}
324

325
int ObPLPackage::get_var(int64_t var_idx, const ObPLVar *&var) const
326
{
327
  int ret = OB_SUCCESS;
328
  var = NULL;
329
  if (var_idx < 0 || var_idx >= var_table_.count()) {
330
     LOG_WARN("var index invalid", K(var_idx), K(ret));
331
  } else {
332
    var = var_table_.at(var_idx);
333
  }
334
  return ret;
335
}
336

337
int ObPLPackage::add_condition(ObPLCondition *value)
338
{
339
  int ret = OB_SUCCESS;
340
  OZ (condition_table_.push_back(value));
341
  return ret;
342
}
343

344
int ObPLPackage::get_condition(const ObString &condition_name, const ObPLCondition *&value)
345
{
346
  int ret = OB_SUCCESS;
347
  value = NULL;
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())) {
354
      value = tmp;
355
      break;
356
    }
357
  }
358
  return ret;
359
}
360

361
int ObPLPackage::get_cursor(int64_t cursor_idx, const ObPLCursor *&cursor) const
362
{
363
  int ret = OB_SUCCESS;
364
  cursor = NULL;
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));
368
  }
369
  return ret;
370
}
371

372
int ObPLPackage::get_cursor(
373
  int64_t package_id, int64_t routine_id, int64_t index, const ObPLCursor *&cursor) const
374
{
375
  int ret = OB_SUCCESS;
376
  cursor = NULL;
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) {
383
      cursor = it;
384
      break;
385
    }
386
  }
387
  return ret;
388
}
389

390
int ObPLPackage::get_cursor(
391
  const ObString &cursor_name, const ObPLCursor *&cursor, int64_t &cursor_idx) const
392
{
393
  int ret = OB_SUCCESS;
394
  cursor = NULL;
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)) {
402
      cursor = it;
403
      cursor_idx = i;
404
      break;
405
    }
406
  }
407
  return ret;
408
}
409

410
int ObPLPackage::add_type(ObUserDefinedType *type)
411
{
412
  int ret = OB_SUCCESS;
413
  if (OB_FAIL(type_table_.push_back(type))) {
414
    LOG_WARN("add user type table failed", K(ret));
415
  }
416
  return ret;
417
}
418

419
int ObPLPackage::get_type(const common::ObString type_name, const ObUserDefinedType *&type) const
420
{
421
  int ret = OB_SUCCESS;
422
  type = NULL;
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());
429
      } else {
430
        type = tmp_type;
431
      }
432
    }
433
  }
434
  return ret;
435
}
436

437
int ObPLPackage::get_type(uint64_t type_id, const ObUserDefinedType *&type) const
438
{
439
  int ret = OB_SUCCESS;
440
  type = NULL;
441
  if (OB_INVALID_ID == type_id) {
442
    LOG_WARN("type id invalid", K(type_id), K(ret));
443
  } else {
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));
449
      } else {
450
        if (tmp_type->get_user_type_id() == type_id) {
451
          type = tmp_type;
452
        }
453
      }
454
    }
455
  }
456
  return ret;
457
}
458
} // end namespace pl
459
} // end namespace oceanbase
460

461

462

463

464

465

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.