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 "ob_pl_dblink_guard.h"
16
#include "share/rc/ob_tenant_base.h"
17
#include "pl/ob_pl_type.h"
18
#include "sql/dblink/ob_dblink_utils.h"
19
#include "sql/session/ob_sql_session_info.h"
20
#include "pl/ob_pl_stmt.h"
21
#ifdef OB_BUILD_ORACLE_PL
22
#include "lib/oracleclient/ob_oci_metadata.h"
23
#include "pl/dblink/ob_pl_dblink_util.h"
30
typedef common::sqlclient::DblinkDriverProto DblinkDriverProto;
32
int ObPLDbLinkGuard::get_routine_infos_with_synonym(sql::ObSQLSessionInfo &session_info,
33
share::schema::ObSchemaGetterGuard &schema_guard,
34
const ObString &dblink_name,
35
const ObString &part1,
36
const ObString &part2,
37
const ObString &part3,
38
common::ObIArray<const share::schema::ObIRoutineInfo *> &routine_infos)
41
#ifndef OB_BUILD_ORACLE_PL
42
ret = OB_NOT_SUPPORTED;
43
LOG_USER_ERROR(OB_NOT_SUPPORTED, "PL dblink");
45
const uint64_t tenant_id = MTL_ID();
46
const ObDbLinkSchema *dblink_schema = NULL;
47
DblinkDriverProto link_type = common::sqlclient::DBLINK_UNKNOWN;
48
common::sqlclient::dblink_param_ctx param_ctx;
49
param_ctx.pool_type_ = common::sqlclient::DblinkPoolType::DBLINK_POOL_SCHEMA;
50
common::ObDbLinkProxy *dblink_proxy = NULL;
51
common::sqlclient::ObISQLConnection *dblink_conn = NULL;
55
ObString sub_object_name;
57
OZ (schema_guard.get_dblink_schema(tenant_id, dblink_name, dblink_schema), tenant_id, dblink_name);
58
OV (OB_NOT_NULL(dblink_schema), OB_DBLINK_NOT_EXIST_TO_ACCESS, dblink_name);
59
OZ (ObPLDblinkUtil::init_dblink(dblink_proxy, dblink_conn, session_info, schema_guard, dblink_name, link_type));
60
CK (OB_NOT_NULL(dblink_proxy));
61
CK (OB_NOT_NULL(dblink_conn));
62
OZ (ObPLDblinkUtil::print_full_name(alloc_, full_name, part1, part2, part3));
63
OZ (dblink_name_resolve(dblink_proxy,
72
OZ (get_dblink_routine_infos(dblink_proxy,
81
#define CHECK_NOT_SUPPORT_TYPE(will_check_type) \
82
if (ob_is_nvarchar2(will_check_type) || ob_is_nchar(will_check_type)) { \
83
ret = OB_NOT_SUPPORTED; \
84
LOG_WARN("not support type", K(ret), K(will_check_type)); \
85
LOG_USER_ERROR(OB_NOT_SUPPORTED, "NCHAR/NVARCHAR2 in PL dblink"); \
88
#define CHECK_RECORD_TYPE(udt_record) \
89
const ObRecordType *record_type = static_cast<const ObRecordType *>(udt_record); \
90
OV (OB_NOT_NULL(record_type)); \
91
for (int64_t mem_idx = 0; OB_SUCC(ret) && mem_idx < record_type->get_member_count(); mem_idx++) { \
92
const ObPLDataType *type = record_type->get_record_member_type(mem_idx); \
93
OV (OB_NOT_NULL(type)); \
94
if (OB_SUCC(ret) && !ob_is_extend(type->get_obj_type())) { \
95
CHECK_NOT_SUPPORT_TYPE(type->get_obj_type()); \
99
const ObIRoutineInfo *info = NULL;
100
for (int64_t i = 0; OB_SUCC(ret) && i < routine_infos.count(); i++) {
101
OV (OB_NOT_NULL(info = routine_infos.at(i)));
102
for(int64_t param_idx = 0; OB_SUCC(ret) && param_idx < info->get_param_count(); param_idx++) {
103
ObIRoutineParam *param = NULL;
104
ObRoutineParam *routine_param = NULL;
105
OZ (info->get_routine_param(param_idx, param));
106
OV (OB_NOT_NULL(param));
107
OV (OB_NOT_NULL(routine_param = static_cast<ObRoutineParam *>(param)));
109
} else if (!ob_is_extend(routine_param->get_pl_data_type().get_obj_type())) {
110
CHECK_NOT_SUPPORT_TYPE(routine_param->get_pl_data_type().get_obj_type());
111
} else if (routine_param->is_dblink_type()) {
112
const pl::ObUserDefinedType *udt = NULL;
114
const ObString &pkg_name = routine_param->get_type_subname();
115
const ObString &udt_name = routine_param->get_type_name();
116
const ObPLDbLinkInfo *dblink_info = NULL;
117
const uint64_t udt_id = OB_INVALID_ID;
118
bool find_pkg = false;
119
OZ (get_dblink_info(info->get_dblink_id(), dblink_info));
120
OV (OB_NOT_NULL(dblink_info), OB_ERR_UNEXPECTED, K(info->get_dblink_id()));
121
CK (routine_param->get_extended_type_info().count() > 0);
122
OX (db_name = routine_param->get_extended_type_info().at(0));
123
OZ (dblink_info->get_udt_from_cache(db_name, pkg_name, udt_name, udt, find_pkg));
124
CK (OB_NOT_NULL(udt));
126
} else if (udt->is_record_type()) {
127
const ObRecordType *record_type = static_cast<const ObRecordType *>(udt);
128
OV (OB_NOT_NULL(record_type));
129
for (int64_t mem_idx = 0; OB_SUCC(ret) && mem_idx < record_type->get_member_count(); mem_idx++) {
130
const ObPLDataType *type = record_type->get_record_member_type(mem_idx);
131
OV (OB_NOT_NULL(type));
132
if (OB_SUCC(ret) && !ob_is_extend(type->get_obj_type())) {
133
CHECK_NOT_SUPPORT_TYPE(type->get_obj_type());
136
} else if (udt->is_collection_type()) {
137
const ObCollectionType *coll_type = static_cast<const ObCollectionType *>(udt);
138
OV (OB_NOT_NULL(coll_type));
140
if (coll_type->get_element_type().is_record_type()) {
141
const pl::ObUserDefinedType *udt2 = NULL;
142
OZ (get_dblink_type_by_id(extract_package_id(coll_type->get_element_type().get_user_type_id()),
143
coll_type->get_element_type().get_user_type_id(), udt2));
144
OV (OB_NOT_NULL(udt2));
145
CHECK_RECORD_TYPE(udt2);
146
} else if (!ob_is_extend(coll_type->get_element_type().get_obj_type())) {
147
CHECK_NOT_SUPPORT_TYPE(coll_type->get_element_type().get_obj_type());
155
#undef CHECK_RECORD_TYPE
156
#undef CHECK_NOT_SUPPORT_TYPE
157
if (OB_NOT_NULL(dblink_proxy) && OB_NOT_NULL(dblink_conn)) {
158
int tmp_ret = OB_SUCCESS;
159
if (OB_SUCCESS != (tmp_ret = dblink_proxy->release_dblink(link_type, dblink_conn))) {
160
LOG_WARN("failed to relese connection", K(tmp_ret));
170
int ObPLDbLinkGuard::get_dblink_type_with_synonym(sql::ObSQLSessionInfo &session_info,
171
share::schema::ObSchemaGetterGuard &schema_guard,
172
const ObString &dblink_name,
173
const ObString &part1,
174
const ObString &part2,
175
const ObString &part3,
176
const pl::ObUserDefinedType *&udt)
178
int ret = OB_SUCCESS;
179
#ifndef OB_BUILD_ORACLE_PL
180
ret = OB_NOT_SUPPORTED;
181
LOG_USER_ERROR(OB_NOT_SUPPORTED, "PL dblink");
183
common::ObDbLinkProxy *dblink_proxy = NULL;
184
common::sqlclient::ObISQLConnection *dblink_conn = NULL;
185
common::sqlclient::DblinkDriverProto link_type = DBLINK_UNKNOWN;
186
OZ (ObPLDblinkUtil::init_dblink(dblink_proxy, dblink_conn, session_info, schema_guard, dblink_name, link_type));
187
CK (OB_NOT_NULL(dblink_proxy));
188
CK (OB_NOT_NULL(dblink_conn));
191
ObString schema_name;
192
ObString object_name;
193
ObString sub_object_name;
195
const ObDbLinkSchema *dblink_schema = NULL;
196
OZ (schema_guard.get_dblink_schema(MTL_ID(), dblink_name, dblink_schema), dblink_name);
197
OV (OB_NOT_NULL(dblink_schema), OB_ERR_UNEXPECTED, dblink_name);
198
OZ (ObPLDblinkUtil::print_full_name(alloc_, full_name, part1, part2, part3));
199
OZ (dblink_name_resolve(dblink_proxy,
208
OV (static_cast<int64_t>(ObObjectType::PACKAGE) == object_type);
209
OZ (get_dblink_type_by_name(dblink_proxy,
219
if (OB_NOT_NULL(dblink_proxy) && OB_NOT_NULL(dblink_conn)) {
220
int tmp_ret = OB_SUCCESS;
221
if (OB_SUCCESS != (tmp_ret = dblink_proxy->release_dblink(link_type, dblink_conn))) {
222
LOG_WARN("failed to relese connection", K(tmp_ret));
232
int ObPLDbLinkGuard::get_dblink_routine_infos(common::ObDbLinkProxy *dblink_proxy,
233
common::sqlclient::ObISQLConnection *dblink_conn,
234
sql::ObSQLSessionInfo &session_info,
235
share::schema::ObSchemaGetterGuard &schema_guard,
236
const ObString &dblink_name,
237
const ObString &db_name,
238
const ObString &pkg_name,
239
const ObString &routine_name,
240
common::ObIArray<const share::schema::ObIRoutineInfo *> &routine_infos)
242
int ret = OB_SUCCESS;
243
#ifndef OB_BUILD_ORACLE_PL
244
ret = OB_NOT_SUPPORTED;
245
LOG_USER_ERROR(OB_NOT_SUPPORTED, "PL dblink");
247
routine_infos.reset();
248
const uint64_t tenant_id = MTL_ID();
249
uint64_t dblink_id = OB_INVALID_ID;
250
const share::schema::ObDbLinkSchema *dblink_schema = NULL;
251
const ObPLDbLinkInfo *dblink_info = NULL;
252
OZ (schema_guard.get_dblink_schema(tenant_id, dblink_name, dblink_schema));
253
OX (dblink_id = dblink_schema->get_dblink_id());
254
OV (OB_INVALID_ID != dblink_id, OB_DBLINK_NOT_EXIST_TO_ACCESS, dblink_id);
255
OZ (get_dblink_info(dblink_id, dblink_info));
257
} else if (OB_ISNULL(dblink_info)) {
258
ObPLDbLinkInfo *new_dblink_info = static_cast<ObPLDbLinkInfo *>(alloc_.alloc(sizeof(ObPLDbLinkInfo)));
259
if (OB_ISNULL(new_dblink_info)) {
260
ret = OB_ALLOCATE_MEMORY_FAILED;
261
LOG_WARN("allocate memory failed", K(ret));
263
new_dblink_info = new (new_dblink_info)ObPLDbLinkInfo();
264
new_dblink_info->set_dblink_id(dblink_id);
265
dblink_info = new_dblink_info;
266
OZ (dblink_infos_.push_back(dblink_info));
269
OZ ((const_cast<ObPLDbLinkInfo *>(dblink_info))->get_routine_infos(dblink_proxy,
279
next_link_object_id_));
281
bool is_all_func = true;
282
for (int64_t i = 0; OB_SUCC(ret) && i < routine_infos.count(); i++) {
283
const ObRoutineInfo *r = static_cast<const ObRoutineInfo *>(routine_infos.at(i));
285
if (OB_SUCC(ret) && ObRoutineType::ROUTINE_PROCEDURE_TYPE == r->get_routine_type()) {
290
if (OB_SUCC(ret) && is_all_func) {
291
ret = OB_ERR_NOT_VALID_ROUTINE_NAME;
292
LOG_WARN("ORA-06576: not a valid function or procedure name", K(ret), K(pkg_name), K(routine_name));
299
int ObPLDbLinkGuard::get_dblink_routine_info(uint64_t dblink_id,
302
const share::schema::ObRoutineInfo *&routine_info)
304
int ret = OB_SUCCESS;
305
#ifndef OB_BUILD_ORACLE_PL
306
ret = OB_NOT_SUPPORTED;
307
LOG_USER_ERROR(OB_NOT_SUPPORTED, "PL dblink");
309
const ObPLDbLinkInfo *dblink_info = NULL;
310
if (OB_FAIL(get_dblink_info(dblink_id, dblink_info))) {
311
LOG_WARN("get dblink info failed", K(ret), K(dblink_id));
312
} else if (OB_ISNULL(dblink_info)) {
313
ret = OB_ERR_UNEXPECTED;
314
LOG_WARN("dblink_info is null", K(ret), K(dblink_id));
315
} else if (OB_FAIL(dblink_info->get_routine_info(pkg_id, routine_id, routine_info))) {
316
LOG_WARN("get routine info failed", K(ret), KP(dblink_info), K(pkg_id), K(routine_id));
322
int ObPLDbLinkGuard::dblink_name_resolve(common::ObDbLinkProxy *dblink_proxy,
323
common::sqlclient::ObISQLConnection *dblink_conn,
324
const ObDbLinkSchema *dblink_schema,
325
const common::ObString &full_name,
326
common::ObString &schema,
327
common::ObString &object_name,
328
common::ObString &sub_object_name,
329
int64_t &object_type,
330
ObIAllocator &alloctor)
332
int ret = OB_SUCCESS;
333
#ifndef OB_BUILD_ORACLE_PL
334
ret = OB_NOT_SUPPORTED;
335
LOG_USER_ERROR(OB_NOT_SUPPORTED, "PL dblink");
339
* PROCEDURE NAME_RESOLVE (NAME IN VARCHAR2,
341
* SCHEMA1 OUT VARCHAR2,
342
* PART1 OUT VARCHAR2,
343
* PART2 OUT VARCHAR2,
344
* DBLINK OUT VARCHAR2,
345
* PART1_TYPE OUT NUMBER,
346
* OBJECT_NUMBER OUT NUMBER);
349
const char *call_proc = "declare "
350
" object_number number; "
352
" dbms_utility.name_resolve(:name, "
361
if (OB_ISNULL(dblink_proxy)) {
362
ret = OB_ERR_UNEXPECTED;
363
LOG_WARN("dblink_proxy is NULL", K(ret));
364
} else if (OB_FAIL(dblink_proxy->dblink_prepare(dblink_conn, call_proc))) {
365
LOG_WARN("prepare sql failed", K(ret), K(ObString(call_proc)));
368
ObString full_name_copy = full_name;
369
const int64_t ident_size = pl::OB_MAX_PL_IDENT_LENGTH + 1;
371
char schema1[ident_size];
372
char part1[ident_size];
373
char part2[ident_size];
374
char dblink[ident_size];
376
int32_t indicator = 0;
377
memset(schema1, 0, ident_size);
378
memset(part1, 0, ident_size);
379
memset(part2, 0, ident_size);
380
memset(dblink, 0, ident_size);
381
int32_t oci_sql_str = static_cast<int32_t>(OciDataType::OCI_SQLT_STR);
382
int32_t oci_sql_int = static_cast<int32_t>(OciDataType::OCI_SQLT_INT);
383
#define BIND_BASIC_BY_POS(param_pos, param, param_size, param_type) \
384
if (FAILEDx(dblink_proxy->dblink_bind_basic_type_by_pos(dblink_conn, \
390
LOG_WARN("bind param failed", K(ret), K(param_pos), K(param_size), K(param_type)); \
392
BIND_BASIC_BY_POS(1, full_name_copy.ptr(), static_cast<int64_t>(full_name_copy.length() + 1), oci_sql_str);
393
BIND_BASIC_BY_POS(2, &context, static_cast<int64_t>(sizeof(int)), oci_sql_int);
394
BIND_BASIC_BY_POS(3, schema1, ident_size, oci_sql_str);
395
BIND_BASIC_BY_POS(4, part1, ident_size, oci_sql_str);
396
BIND_BASIC_BY_POS(5, part2, ident_size, oci_sql_str);
397
BIND_BASIC_BY_POS(6, dblink, ident_size, oci_sql_str);
398
BIND_BASIC_BY_POS(7, &part1_type, static_cast<int64_t>(sizeof(int)), oci_sql_int);
399
if (FAILEDx(dblink_proxy->dblink_execute_proc(dblink_conn))) {
400
const DblinkDriverProto link_type = static_cast<DblinkDriverProto>(dblink_schema->get_driver_proto());
401
LOG_WARN("read link failed", K(ret), K(ObString(call_proc)));
403
switch (part1_type) {
404
case OracleObjectType::ORA_PROCEUDRE:
406
object_type = static_cast<int64_t>(ObObjectType::PROCEDURE);
408
case OracleObjectType::ORA_PACKAGE:
410
object_type = static_cast<int64_t>(ObObjectType::PACKAGE);
413
ret = OB_ERR_NOT_VALID_ROUTINE_NAME;
414
LOG_WARN("remote object type not support", K(ret), K(full_name));
417
OZ (ob_write_string(alloctor, ObString(schema1), schema));
418
OZ (ob_write_string(alloctor, ObString(part1), object_name));
419
OZ (ob_write_string(alloctor, ObString(part2), sub_object_name));
421
#undef BIND_BASIC_BY_POS
427
int ObPLDbLinkGuard::get_dblink_type_by_name(common::ObDbLinkProxy *dblink_proxy,
428
common::sqlclient::ObISQLConnection *dblink_conn,
429
sql::ObSQLSessionInfo &session_info,
430
share::schema::ObSchemaGetterGuard &schema_guard,
431
const common::ObString &dblink_name,
432
const common::ObString &db_name,
433
const common::ObString &pkg_name,
434
const common::ObString &udt_name,
435
const pl::ObUserDefinedType *&udt)
437
int ret = OB_SUCCESS;
438
#ifndef OB_BUILD_ORACLE_PL
439
ret = OB_NOT_SUPPORTED;
440
LOG_USER_ERROR(OB_NOT_SUPPORTED, "PL dblink");
442
const uint64_t tenant_id = MTL_ID();
443
uint64_t dblink_id = OB_INVALID_ID;
444
const share::schema::ObDbLinkSchema *dblink_schema = NULL;
445
const ObPLDbLinkInfo *dblink_info = NULL;
446
OZ (schema_guard.get_dblink_schema(tenant_id, dblink_name, dblink_schema));
447
OV (OB_NOT_NULL(dblink_schema), OB_DBLINK_NOT_EXIST_TO_ACCESS, dblink_name);
448
OV (OB_INVALID_ID != (dblink_id = dblink_schema->get_dblink_id()), OB_DBLINK_NOT_EXIST_TO_ACCESS, dblink_id);
449
OZ (get_dblink_info(dblink_id, dblink_info));
451
} else if (OB_ISNULL(dblink_info)) {
452
ObPLDbLinkInfo *new_dblink_info = static_cast<ObPLDbLinkInfo *>(alloc_.alloc(sizeof(ObPLDbLinkInfo)));
453
if (OB_ISNULL(new_dblink_info)) {
454
ret = OB_ALLOCATE_MEMORY_FAILED;
455
LOG_WARN("allocate memory failed", K(ret));
457
new_dblink_info = new (new_dblink_info)ObPLDbLinkInfo();
458
new_dblink_info->set_dblink_id(dblink_id);
459
dblink_info = new_dblink_info;
460
OZ (dblink_infos_.push_back(dblink_info));
463
OZ ((const_cast<ObPLDbLinkInfo *>(dblink_info))->get_udt_by_name(dblink_proxy, dblink_conn, session_info,
464
schema_guard, alloc_, dblink_name, db_name, pkg_name,
465
udt_name, udt, next_link_object_id_));
470
int ObPLDbLinkGuard::get_dblink_type_by_id(const uint64_t mask_dblink_id,
471
const uint64_t udt_id,
472
const pl::ObUserDefinedType *&udt)
474
int ret = OB_SUCCESS;
475
#ifndef OB_BUILD_ORACLE_PL
476
ret = OB_NOT_SUPPORTED;
477
LOG_USER_ERROR(OB_NOT_SUPPORTED, "PL dblink");
479
uint64_t dblink_id = mask_dblink_id & ~common::OB_MOCK_DBLINK_UDT_ID_MASK;
480
const ObPLDbLinkInfo *dblink_info = NULL;
481
for (int64_t i = 0; OB_SUCC(ret) && OB_ISNULL(dblink_info) && i < dblink_infos_.count(); i++) {
482
if (OB_ISNULL(dblink_infos_.at(i))) {
483
ret = OB_ERR_UNEXPECTED;
484
LOG_WARN("dblink_info is null", K(ret), K(i));
485
} else if (dblink_id == dblink_infos_.at(i)->get_dblink_id()) {
486
dblink_info = dblink_infos_.at(i);
487
OZ (dblink_info->get_udt_by_id(udt_id, udt));
494
int ObPLDbLinkGuard::get_dblink_type_by_name(const uint64_t dblink_id,
495
const common::ObString &db_name,
496
const common::ObString &pkg_name,
497
const common::ObString &udt_name,
498
const pl::ObUserDefinedType *&udt)
500
int ret = OB_SUCCESS;
501
#ifndef OB_BUILD_ORACLE_PL
502
ret = OB_NOT_SUPPORTED;
503
LOG_USER_ERROR(OB_NOT_SUPPORTED, "PL dblink");
505
const ObPLDbLinkInfo *dblink_info = NULL;
506
for (int64_t i = 0; OB_SUCC(ret) && i < dblink_infos_.count(); i++) {
507
if (OB_ISNULL(dblink_infos_.at(i))) {
508
ret = OB_ERR_UNEXPECTED;
509
LOG_WARN("dblink_info is null", K(ret), K(i));
510
} else if (dblink_id == dblink_infos_.at(i)->get_dblink_id()) {
511
dblink_info = dblink_infos_.at(i);
512
bool find_pkg = false;
513
OZ (dblink_info->get_udt_from_cache(db_name, pkg_name, udt_name, udt, find_pkg));
521
#ifdef OB_BUILD_ORACLE_PL
522
int ObPLDbLinkGuard::get_dblink_info(const uint64_t dblink_id,
523
const ObPLDbLinkInfo *&dblink_info)
525
int ret = OB_SUCCESS;
526
for (int64_t i = 0; OB_SUCC(ret) && OB_ISNULL(dblink_info) && i < dblink_infos_.count(); i++) {
527
if (OB_ISNULL(dblink_infos_.at(i))) {
528
ret = OB_ERR_UNEXPECTED;
529
LOG_WARN("dblink_info is null", K(ret), K(i));
531
dblink_info = dblink_infos_.at(i);