diff --git a/deps/oblib/src/common/object/ob_obj_funcs.h b/deps/oblib/src/common/object/ob_obj_funcs.h index ebd097f3e5..7130d4b289 100644 --- a/deps/oblib/src/common/object/ob_obj_funcs.h +++ b/deps/oblib/src/common/object/ob_obj_funcs.h @@ -817,14 +817,22 @@ DEF_NUMBER_FUNCS(ObNumberFloatType, number_float); int ret = common::OB_SUCCESS; \ static const char *CAST_PREFIX_ORACLE = "TO_DATE('"; \ static const char *CAST_SUFFIX_ORACLE = "', 'YYYY-MM-DD HH24:MI:SS')"; \ + static const char *CAST_PREFIX_MYSQL_TIMESTAMP = "TIMESTAMP"; \ + static const char *CAST_PREFIX_MYSQL_DATETIME = "DATETIME"; \ static const char *NORMAL_SUFFIX = "'"; \ const ObTimeZoneInfo *tz_info = params.tz_info_; \ const char *NORMAL_PREFIX = params.beginning_space_ ? "' " : "'"; \ ObString str(static_cast(length - pos - 1), 0, buffer + pos + 1); \ if (OB_SUCC(ret)) { \ - const char *fmt_prefix = params.need_cast_expr_ && lib::is_oracle_mode() ? \ - CAST_PREFIX_ORACLE : NORMAL_PREFIX; \ - ret = databuff_printf(buffer, length, pos, "%s", fmt_prefix); \ + if (lib::is_oracle_mode() && params.need_cast_expr_) { \ + ret = databuff_printf(buffer, length, pos, "%s", CAST_PREFIX_ORACLE); \ + } else if (params.print_const_expr_type_ && !lib::is_oracle_mode() && ObDateTimeType == obj.get_type()) { \ + ret = databuff_printf(buffer, length, pos, "CAST('"); \ + } else if (params.print_const_expr_type_ && !lib::is_oracle_mode() && ObTimestampType == obj.get_type()) { \ + ret = databuff_printf(buffer, length, pos, "%s %s", CAST_PREFIX_MYSQL_TIMESTAMP, NORMAL_PREFIX);\ + } else { \ + ret = databuff_printf(buffer, length, pos, "%s", NORMAL_PREFIX); \ + } \ } \ if (OB_SUCC(ret)) { \ if (ObTimestampType != obj.get_type()) { \ @@ -835,10 +843,14 @@ DEF_NUMBER_FUNCS(ObNumberFloatType, number_float); obj.get_scale(), buffer, length, pos); \ } \ if (OB_SUCC(ret)) { \ - const char *fmt_suffix = params.need_cast_expr_ && lib::is_oracle_mode() ? \ - CAST_SUFFIX_ORACLE : NORMAL_SUFFIX; \ - ret = databuff_printf(buffer, length, pos, "%s", fmt_suffix); \ - } \ + if (params.print_const_expr_type_ && !lib::is_oracle_mode() && ObDateTimeType == obj.get_type()) { \ + ret = databuff_printf(buffer, length, pos, "' AS %s)", CAST_PREFIX_MYSQL_DATETIME); \ + } else { \ + const char *fmt_suffix = params.need_cast_expr_ && lib::is_oracle_mode() ? \ + CAST_SUFFIX_ORACLE : NORMAL_SUFFIX; \ + ret = databuff_printf(buffer, length, pos, "%s", fmt_suffix); \ + } \ + } \ return ret; \ } \ \ @@ -913,7 +925,12 @@ DEF_DATETIME_FUNCS(ObTimestampType, timestamp, int64_t); const ObObjPrintParams ¶ms) \ { \ UNUSED(params); \ - int ret = databuff_printf(buffer, length, pos, "'"); \ + int ret = OB_SUCCESS; \ + if (params.print_const_expr_type_ && !lib::is_oracle_mode() && ObDateType == obj.get_type()) { \ + ret = databuff_printf(buffer, length, pos, "DATE '"); \ + } else { \ + ret = databuff_printf(buffer, length, pos, "'"); \ + } \ if (OB_SUCC(ret)) { \ ret = ObTimeConverter::TYPE##_to_str(obj.get_##TYPE(), buffer, length, pos); \ } \ @@ -978,8 +995,13 @@ DEF_DATE_YEAR_FUNCS(ObDateType, date, int32_t); const ObObjPrintParams ¶ms) \ { \ UNUSED(params); \ - int ret = databuff_printf(buffer, length, pos, "'"); \ - if (OB_SUCC(ret)) { \ + int ret = OB_SUCCESS; \ + if (params.print_const_expr_type_ && !lib::is_oracle_mode() && ObTimeType == obj.get_type()) { \ + ret = databuff_printf(buffer, length, pos, "TIME '"); \ + } else { \ + ret = databuff_printf(buffer, length, pos, "'"); \ + } \ + if (OB_SUCC(ret)) { \ ret = ObTimeConverter::TYPE##_to_str(obj.get_##TYPE(), obj.get_scale(), buffer, length, pos);\ } \ if (OB_SUCC(ret)) { \ diff --git a/deps/oblib/src/common/object/ob_object.h b/deps/oblib/src/common/object/ob_object.h index 18f639f315..86468dbffd 100644 --- a/deps/oblib/src/common/object/ob_object.h +++ b/deps/oblib/src/common/object/ob_object.h @@ -37,6 +37,10 @@ class ObjTest; class ObSqlString; } } +namespace sql +{ +class ObExecContext; +} namespace common { @@ -1081,17 +1085,20 @@ struct ObObjPrintParams ObObjPrintParams (const ObTimeZoneInfo *tz_info, ObCollationType cs_type): tz_info_(tz_info), cs_type_(cs_type), - print_flags_(0) + print_flags_(0), + exec_ctx_(NULL) {} ObObjPrintParams (const ObTimeZoneInfo *tz_info): tz_info_(tz_info), cs_type_(CS_TYPE_UTF8MB4_GENERAL_CI), - print_flags_(0) + print_flags_(0), + exec_ctx_(NULL) {} ObObjPrintParams (): tz_info_(NULL), cs_type_(CS_TYPE_UTF8MB4_GENERAL_CI), - print_flags_(0) + print_flags_(0), + exec_ctx_(NULL) {} TO_STRING_KV(K_(tz_info), K_(cs_type),K_(print_flags)); const ObTimeZoneInfo *tz_info_; @@ -1106,9 +1113,21 @@ struct ObObjPrintParams uint32_t beginning_space_:1; uint32_t for_dblink_:1; uint32_t binary_string_print_hex_:1; - uint32_t reserved_:25; + uint32_t need_print_converter_:1; + uint32_t print_const_expr_type_:1; + uint32_t reserved_:23; }; }; + + /** + * MySQL only + * The limit expr may no longer be a constant number after transformer. + * So, set exec_ctx_ if the stmt is rewritten. + * If exec_ctx_ is not null, Printer will calculate the value of limit expr and output. + * e.g. "limit (1 + 1)" will be output as "limit 2" + * + */ + sql::ObExecContext *exec_ctx_; }; // sizeof(ObObjValue)=8 diff --git a/deps/oblib/src/lib/CMakeLists.txt b/deps/oblib/src/lib/CMakeLists.txt index 2fdafb7041..0448d34cef 100644 --- a/deps/oblib/src/lib/CMakeLists.txt +++ b/deps/oblib/src/lib/CMakeLists.txt @@ -163,6 +163,7 @@ ob_set_subtarget(oblib_lib lock ob_set_subtarget(oblib_lib mysqlclient mysqlclient/ob_isql_client.cpp + mysqlclient/ob_dblink_error_trans.cpp mysqlclient/ob_mysql_connection.cpp mysqlclient/ob_mysql_connection_pool.cpp mysqlclient/ob_mysql_prepared_param.cpp diff --git a/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.cpp b/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.cpp new file mode 100644 index 0000000000..aa0e60e66d --- /dev/null +++ b/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.cpp @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2021 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 LIB_MYSQLC +#include "lib/mysqlclient/ob_dblink_error_trans.h" + +int __attribute__((weak)) get_oracle_errno(int index) +{ + return oceanbase::OB_SUCCESS; +} + +int __attribute__((weak)) get_mysql_errno(int index) +{ + return oceanbase::OB_SUCCESS; +} + +const char* __attribute__((weak)) get_oracle_str_error(int index) +{ + return NULL; +} + +const char* __attribute__((weak)) get_mysql_str_error(int index) +{ + return NULL; +} + + +namespace oceanbase +{ +namespace common +{ + +int sqlclient::ObDblinkErrorTrans::external_errno_to_ob_errno(bool is_oracle_err, + int external_errno, + const char *external_errmsg, + int &ob_errno) { + int ret = OB_SUCCESS; + external_errno = abs(external_errno); + if (OB_SUCCESS != external_errno) { + const char *oracle_msg_prefix = "ORA"; + if (external_errno >= 2000 && // google "Client Error Message Reference" + external_errno <= 2075 && // you will known errno in [2000, 2075] is client error at dev.mysql.com + (!is_oracle_err || + (is_oracle_err && + OB_NOT_NULL(external_errmsg) && + 0 != std::memcmp(oracle_msg_prefix, external_errmsg, + std::min(STRLEN(oracle_msg_prefix), STRLEN(external_errmsg)))))) { + ob_errno = external_errno; // do not map, show user client errno directly. + } else { + ob_errno = OB_ERR_DBLINK_REMOTE_ECODE; // default ob_errno, if external_errno can not map to any valid ob_errno + if (OB_ISNULL(external_errmsg)) { + for (int i = 0; i < oceanbase::common::OB_MAX_ERROR_CODE; ++i) { + if (external_errno == (is_oracle_err ? get_oracle_errno(i) : get_mysql_errno(i))) { + ob_errno = -i; + break; + } + } + } else { + ObEditDistance ed; + int64_t edit_dist = 0x7fffffffffffffff; + int64_t min_edit_dist = 0x7fffffffffffffff; + for (int i = 0; i < oceanbase::common::OB_MAX_ERROR_CODE; ++i) { + if (external_errno == (is_oracle_err ? get_oracle_errno(i) : get_mysql_errno(i))) { + const char *external_errstr = (is_oracle_err ? get_oracle_str_error(i) : get_mysql_str_error(i)); + if (OB_ISNULL(external_errstr)) { + // In the case of a null pointer boundary + edit_dist = 0x7ffffffffffffffe; + } else { + // The edit distance between the strings is used to measure their similarity. + // The smaller the edit distance, the greater the similarity, so as to find the most similar error message. + ObEditDistance::cal_edit_distance(external_errmsg, external_errstr, STRLEN(external_errmsg), STRLEN(external_errstr), edit_dist); + } + if (edit_dist < min_edit_dist) { + ob_errno = -i; + min_edit_dist = edit_dist; + if (0 == min_edit_dist) { + break; + } + } + } + } + } + } + } + return ret; +} + +} // end namespace common +} // end namespace oceanbase \ No newline at end of file diff --git a/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.h b/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.h new file mode 100644 index 0000000000..abb2c20b40 --- /dev/null +++ b/deps/oblib/src/lib/mysqlclient/ob_dblink_error_trans.h @@ -0,0 +1,47 @@ +#ifndef OBDBLINKERROR_H +#define OBDBLINKERROR_H +#include "lib/utility/ob_edit_distance.h" +#include "lib/ob_errno.h" + +namespace oceanbase +{ +namespace common +{ +namespace sqlclient +{ + +#define TRANSLATE_CLIENT_ERR(ret, errmsg) \ + const int orginal_ret = ret;\ + bool is_oracle_err = lib::is_oracle_mode();\ + int translate_ret = OB_SUCCESS;\ + if (OB_SUCCESS == ret) {\ + } else if (OB_SUCCESS != (translate_ret = oceanbase::common::sqlclient::ObDblinkErrorTrans::\ + external_errno_to_ob_errno(is_oracle_err, orginal_ret, errmsg, ret))) {\ + LOG_WARN("failed to translate client error code", K(translate_ret), K(orginal_ret), K(ret), K(is_oracle_err), K(errmsg));\ + } else {\ + LOG_WARN("succ to translate client error code", K(translate_ret), K(orginal_ret), K(ret), K(is_oracle_err), K(errmsg));\ + } + +#define TRANSLATE_CLIENT_ERR_2(ret, is_oracle_err, errmsg) \ + const int orginal_ret = ret;\ + int translate_ret = OB_SUCCESS;\ + if (OB_SUCCESS == ret) {\ + } else if (OB_SUCCESS != (translate_ret = oceanbase::common::sqlclient::ObDblinkErrorTrans::\ + external_errno_to_ob_errno(is_oracle_err, orginal_ret, errmsg, ret))) {\ + LOG_WARN("failed to translate client error code", K(translate_ret), K(orginal_ret), K(ret), K(is_oracle_err), K(errmsg));\ + } else {\ + LOG_WARN("succ to translate client error code", K(translate_ret), K(orginal_ret), K(ret), K(is_oracle_err), K(errmsg));\ + } + +class ObDblinkErrorTrans { +public: + static int external_errno_to_ob_errno(bool is_oci_client, + int external_errno, + const char *external_errmsg, + int &ob_errno); +}; + +} // namespace sqlclient +} // namespace common +} // namespace oceanbase +#endif //OBDBLINKERROR_H \ No newline at end of file diff --git a/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h b/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h index 77833606fd..84ab50dd84 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h +++ b/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h @@ -80,9 +80,15 @@ public: sessid_(-1), consumer_group_id_(0), has_reverse_link_credentials_(false), - usable_(true) + usable_(true), + last_set_sql_mode_cstr_(NULL), + last_set_sql_mode_cstr_buf_size_(0) {} - virtual ~ObISQLConnection() {} + virtual ~ObISQLConnection() { + allocator_.reset(); + last_set_sql_mode_cstr_buf_size_ = 0; + last_set_sql_mode_cstr_ = NULL; + } // sql execute interface virtual int execute_read(const uint64_t tenant_id, const char *sql, @@ -135,7 +141,35 @@ public: virtual void set_use_external_session(bool v) { UNUSED(v); } virtual int64_t get_cluster_id() const { return common::OB_INVALID_ID; } void set_init_remote_env(bool flag) { is_init_remote_env_ = flag;} - bool get_init_remote_env() const { return is_init_remote_env_; } + int is_session_inited(const char * sql_mode_cstr, bool &is_inited) { + int ret = OB_SUCCESS; + is_inited = false; + int64_t sql_mode_len = 0; + if (lib::is_oracle_mode()) { + is_inited = is_init_remote_env_; + } else if (OB_ISNULL(sql_mode_cstr)) { + ret = OB_ERR_UNEXPECTED; + } else if (FALSE_IT([&]{ + is_inited = (0 == ObString(sql_mode_cstr).compare(last_set_sql_mode_cstr_)); + sql_mode_len = STRLEN(sql_mode_cstr); + }())) { + } else if (!is_inited) { + if (sql_mode_len >= last_set_sql_mode_cstr_buf_size_) { + void *buf = NULL; + if (OB_ISNULL(buf = allocator_.alloc((sql_mode_len * 2)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + } else { + last_set_sql_mode_cstr_ = (char *)buf; + last_set_sql_mode_cstr_buf_size_ = sql_mode_len * 2; + } + } + if (OB_SUCC(ret)) { + MEMCPY(last_set_sql_mode_cstr_, sql_mode_cstr, sql_mode_len); + last_set_sql_mode_cstr_[sql_mode_len] = 0; + } + } + return ret; + } void set_group_id(const int64_t v) {consumer_group_id_ = v; } int64_t get_group_id() const {return consumer_group_id_; } void set_reverse_link_creadentials(bool flag) { has_reverse_link_credentials_ = flag; } @@ -145,13 +179,16 @@ public: virtual int ping() { return OB_SUCCESS; } protected: bool oracle_mode_; - bool is_init_remote_env_; // for dblink, we have to init remote env with some sql + bool is_init_remote_env_; // for oracle dblink, we have to init remote env with some sql uint64_t dblink_id_; // for dblink, record dblink_id of a connection used by dblink int64_t dblink_driver_proto_; //for dblink, record DblinkDriverProto of a connection used by dblink uint32_t sessid_; int64_t consumer_group_id_; //for resource isolation bool has_reverse_link_credentials_; // for dblink, mark if this link has credentials set bool usable_; // usable_ = false: connection is unusable, should not execute query again. + char *last_set_sql_mode_cstr_; // for mysql dblink to set sql mode + int64_t last_set_sql_mode_cstr_buf_size_; + common::ObArenaAllocator allocator_; }; } // end namespace sqlclient diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.cpp b/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.cpp index 56c78300b1..9211ec8541 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.cpp @@ -20,6 +20,7 @@ #include "lib/profile/ob_trace_id.h" #include "lib/string/ob_sql_string.h" #include "lib/mysqlclient/ob_mysql_read_context.h" +#include "lib/mysqlclient/ob_dblink_error_trans.h" namespace oceanbase { @@ -160,7 +161,7 @@ int ObMySQLConnection::connect(const char *user, const char *pass, const char *d MYSQL *mysql = mysql_real_connect(&mysql_, host, user, pass, db, port, NULL, 0); if (OB_ISNULL(mysql)) { ret = -mysql_errno(&mysql_); - LOG_WARN("fail to connect to mysql server", K(get_sessid()), KCSTRING(host), KCSTRING(user), K(port), + LOG_WARN("fail to connect to mysql server", K(get_sessid()), KCSTRING(host), KCSTRING(user), KCSTRING(db), K(port), "info", mysql_error(&mysql_), K(ret)); } else { /*Note: mysql_real_connect() incorrectly reset the MYSQL_OPT_RECONNECT option @@ -230,8 +231,11 @@ int ObMySQLConnection::connect(const char *user, const char *pass, const char *d MYSQL *mysql = mysql_real_connect(&mysql_, host, user, pass, db, port, NULL, 0); if (OB_ISNULL(mysql)) { ret = -mysql_errno(&mysql_); - LOG_WARN("fail to connect to mysql server", K(get_sessid()), KCSTRING(host), KCSTRING(user), K(port), + LOG_WARN("fail to connect to mysql server", K(get_sessid()), KCSTRING(host), KCSTRING(user), KCSTRING(db), K(port), "info", mysql_error(&mysql_), K(ret)); + if (OB_INVALID_ID != get_dblink_id()) { + TRANSLATE_CLIENT_ERR_2(ret, false, mysql_error(&mysql_)); + } } else { /*Note: mysql_real_connect() incorrectly reset the MYSQL_OPT_RECONNECT option * to its default value before MySQL 5.0.19. Therefore, prior to that version, diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_connection_pool.cpp b/deps/oblib/src/lib/mysqlclient/ob_mysql_connection_pool.cpp index 826c521324..bf0a8ffadc 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_connection_pool.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_connection_pool.cpp @@ -860,6 +860,7 @@ int ObMySQLConnectionPool::do_acquire_dblink(uint64_t dblink_id, const dblink_pa } else { ATOMIC_INC((uint64_t *)&busy_conn_count_); dblink_conn1->set_busy(true); + dblink_conn1->set_dblink_id(dblink_id); dblink_conn1->set_timestamp(::oceanbase::common::ObTimeUtility::current_time()); dblink_conn = static_cast(dblink_conn1); LOG_TRACE("acquire connection from mysql connection pool", K(this), K(busy_conn_count_), KP(dblink_conn), K(dblink_conn1->is_closed()), K(dblink_pool), K(sessid)); diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp index ff20c9fb8c..a77d584fa8 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp @@ -451,7 +451,8 @@ int ObDbLinkProxy::acquire_dblink(uint64_t dblink_id, const dblink_param_ctx ¶m_ctx, ObISQLConnection *&dblink_conn, uint32_t sessid, - int64_t sql_request_level) + int64_t sql_request_level, + const char *set_sql_mode_cstr) { int ret = OB_SUCCESS; ObISQLConnectionPool *dblink_pool = NULL; @@ -462,7 +463,7 @@ int ObDbLinkProxy::acquire_dblink(uint64_t dblink_id, LOG_WARN("failed to get dblink interface", K(ret), K(dblink_type)); } else if (OB_FAIL(dblink_pool->acquire_dblink(dblink_id, param_ctx, dblink_conn, sessid, sql_request_level))) { LOG_WARN("acquire dblink failed", K(ret), K(dblink_id), K(dblink_type)); - } else if (OB_FAIL(prepare_enviroment(dblink_conn, dblink_type))) { + } else if (OB_FAIL(prepare_enviroment(dblink_conn, dblink_type, set_sql_mode_cstr))) { LOG_WARN("failed to prepare dblink env", K(ret)); } else { dblink_conn->set_dblink_id(dblink_id); @@ -471,16 +472,19 @@ int ObDbLinkProxy::acquire_dblink(uint64_t dblink_id, return ret; } -int ObDbLinkProxy::prepare_enviroment(ObISQLConnection *dblink_conn, int link_type) +int ObDbLinkProxy::prepare_enviroment(ObISQLConnection *dblink_conn, int link_type, const char *set_sql_mode_cstr) { int ret = OB_SUCCESS; + bool is_inited = false; if (OB_ISNULL(dblink_conn)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("dblink is null", K(ret)); - } else if (dblink_conn->get_init_remote_env()) { - // do nothing; + } else if (OB_FAIL(dblink_conn->is_session_inited(set_sql_mode_cstr, is_inited))) { + LOG_WARN("failed to get init status", K(ret)); + } else if (is_inited) { + // do nothing } else { - if (OB_FAIL(execute_init_sql(dblink_conn, link_type))) { + if (OB_FAIL(execute_init_sql(dblink_conn, link_type, set_sql_mode_cstr))) { LOG_WARN("failed to execute init sql", K(ret)); } else { LOG_DEBUG("set session variable nls_date_format"); @@ -490,21 +494,42 @@ int ObDbLinkProxy::prepare_enviroment(ObISQLConnection *dblink_conn, int link_ty return ret; } -int ObDbLinkProxy::execute_init_sql(ObISQLConnection *dblink_conn, int link_type) +int ObDbLinkProxy::execute_init_sql(ObISQLConnection *dblink_conn, int link_type, const char *set_sql_mode_cstr) { int ret = OB_SUCCESS; typedef const char * sql_ptr_type; - if (DBLINK_DRV_OB == link_type) { + if (!lib::is_oracle_mode()) { + const int64_t sql_ptr_count = 2; + sql_ptr_type sql_ptr[sql_ptr_count] = {set_sql_mode_cstr, + "set character_set_results = NULL"}; + if (OB_ISNULL(set_sql_mode_cstr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret), KP(set_sql_mode_cstr)); + } else { + ObMySQLStatement stmt; + ObMySQLConnection *mysql_conn = static_cast(dblink_conn); + for (int i = 0; OB_SUCC(ret) && i < sql_ptr_count; ++i) { + if (OB_FAIL(stmt.init(*mysql_conn, sql_ptr[i]))) { + LOG_WARN("create statement failed", K(ret), K(link_type)); + } else if (OB_FAIL(stmt.execute_update())) { + LOG_WARN("execute sql failed", K(ret), K(link_type)); + } else { + // do nothing + } + } + } + } else if (DBLINK_DRV_OB == link_type) { static sql_ptr_type sql_ptr[] = { "set character_set_results = NULL", "set nls_date_format='YYYY-MM-DD HH24:MI:SS'", "set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF'", "set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF TZR TZD'" }; + int64_t sql_ptr_count = sizeof(sql_ptr) / sizeof(sql_ptr_type); // todo statement may different ObMySQLStatement stmt; ObMySQLConnection *mysql_conn = static_cast(dblink_conn); - for (int i = 0; OB_SUCC(ret) && i < sizeof(sql_ptr) / sizeof(sql_ptr_type); ++i) { + for (int i = 0; OB_SUCC(ret) && i < sql_ptr_count; ++i) { if (OB_FAIL(stmt.init(*mysql_conn, sql_ptr[i]))) { LOG_WARN("create statement failed", K(ret), K(link_type)); } else if (OB_FAIL(stmt.execute_update())) { diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.h b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.h index 99d5c47344..1cc1c0ace6 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.h +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.h @@ -177,7 +177,8 @@ public: const sqlclient::dblink_param_ctx ¶m_ctx, sqlclient::ObISQLConnection *&dblink_conn, uint32_t sessid = 0, - int64_t sql_request_level = 0); + int64_t sql_request_level = 0, + const char *set_sql_mode_cstr = NULL); int release_dblink(/*uint64_t dblink_id,*/sqlclient::DblinkDriverProto dblink_type, sqlclient::ObISQLConnection *dblink_conn, uint32_t sessid = 0); int dblink_read(sqlclient::ObISQLConnection *dblink_conn, ReadResult &result, const char *sql); int dblink_write(sqlclient::ObISQLConnection *dblink_conn, int64_t &affected_rows, const char *sql); @@ -185,9 +186,11 @@ public: int switch_dblink_conn_pool(sqlclient::DblinkDriverProto type, sqlclient::ObISQLConnectionPool *&dblink_conn_pool); int set_dblink_pool_charset(uint64_t dblink_id); inline sqlclient::ObDbLinkConnectionPool *get_dblink_conn_pool() { return link_pool_; } - static int execute_init_sql(sqlclient::ObISQLConnection *dblink_conn, int link_type); + static int execute_init_sql(sqlclient::ObISQLConnection *dblink_conn, int link_type, + const char *set_sql_mode_cstr = NULL); private: - int prepare_enviroment(sqlclient::ObISQLConnection *dblink_conn, int link_type); + int prepare_enviroment(sqlclient::ObISQLConnection *dblink_conn, int link_type, + const char *set_sql_mode_cstr = NULL); sqlclient::ObDbLinkConnectionPool *link_pool_; }; diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_result.cpp b/deps/oblib/src/lib/mysqlclient/ob_mysql_result.cpp index 88ec7f3927..f29ecd0ff5 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_result.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_result.cpp @@ -74,49 +74,103 @@ int ObMySQLResult::print_info() const return OB_SUCCESS; } -void ObMySQLResult::format_precision_scale_length(int16_t &precision, int16_t &scale, int32_t &length, - oceanbase::common::ObObjType ob_type, oceanbase::common::ObCollationType cs_type, - DblinkDriverProto link_type, bool old_max_length) const +int ObMySQLResult::format_precision_scale_length(int16_t &precision, int16_t &scale, int32_t &length, + oceanbase::common::ObObjType ob_type, oceanbase::common::ObCollationType meta_cs_type,DblinkDriverProto link_type, bool old_max_length) const { + int ret = OB_SUCCESS; int16_t tmp_precision = precision; int16_t tmp_scale = scale; int32_t tmp_length = length; + int64_t mbmaxlen = 0; // format precision from others to oceanbase - if (ob_is_nstring(ob_type)) { - precision = LS_CHAR; // precision is LS_CHAR means national character set (unicode) - } else if (ObNumberFloatType == ob_type) { - precision = tmp_precision; //bit precision, not decimal precision - } else if (tmp_precision < OB_MIN_NUMBER_PRECISION || tmp_precision > OB_MAX_NUMBER_PRECISION) { - precision = -1; // for other data type, need format it to -1 if precison out of range - } else { - precision = tmp_precision; // for a valid precison([OB_MIN_NUMBER_PRECISION, OB_MAX_NUMBER_PRECISION]), just set it - } - - // format scale from others to oceanbase - if (DBLINK_DRV_OCI == link_type && (ObFloatType == ob_type || ObDoubleType == ob_type)) { - scale = OB_MIN_NUMBER_SCALE - 1; // binary_float and binar_double scale from oci is 0, need set to -85 - } else if (DBLINK_DRV_OCI == link_type && ObDateTimeType == ob_type) { - scale = 0; - } else if (tmp_scale < OB_MIN_NUMBER_SCALE || tmp_scale > OB_MAX_NUMBER_SCALE) { - scale = OB_MIN_NUMBER_SCALE - 1; // format it to -85 if scale out of range - } else { - scale = tmp_scale; // for a valid scale, just set it - } - - // format length from others to oceanbase - if (ob_is_accuracy_length_valid_tc(ob_type)) { - int32_t max_length = 0; - if (old_max_length) { - max_length = OB_MAX_LONGTEXT_LENGTH_OLD; - } else { - max_length = OB_MAX_LONGTEXT_LENGTH; + if (!lib::is_oracle_mode()) { + switch (ob_type) { + case ObNumberType: { // for mysql decimal + if (2 == length) { + precision = 1; + } else { + precision = length - 2; + } + length = -1; + break; + } + case ObDoubleType: // for mysql double type and float type + case ObFloatType: { + precision = length; + length = -1; + if (scale > precision) { + scale = -1; + precision = -1; + } + break; + } + case ObCharType: + case ObVarcharType: { + if (OB_FAIL(common::ObCharset::get_mbmaxlen_by_coll(meta_cs_type, mbmaxlen))) { + LOG_WARN("fail to get mbmaxlen", K(meta_cs_type), K(ret)); + } else { + length /= mbmaxlen; + precision = -1; + scale = -1; + } + break; + } + case ObTinyIntType: + case ObSmallIntType: + case ObInt32Type: + case ObIntType: + case ObBitType: { + precision = length; + length = -1; + scale = -1; + break; + } + default: + break; } - if (tmp_length < 1 || tmp_length > max_length) { - length = max_length; + } else { + if (ob_is_nstring(ob_type)) { + precision = LS_CHAR; // precision is LS_CHAR means national character set (unicode) + } else if (ObNumberFloatType == ob_type) { + precision = tmp_precision; //bit precision, not decimal precision + } else if (tmp_precision < OB_MIN_NUMBER_PRECISION || tmp_precision > OB_MAX_NUMBER_PRECISION) { + precision = -1; // for other data type, need format it to -1 if precison out of range } else { - length = tmp_length; + precision = tmp_precision; // for a valid precison([OB_MIN_NUMBER_PRECISION, OB_MAX_NUMBER_PRECISION]), just set it + } + + // format scale from others to oceanbase + if (DBLINK_DRV_OCI == link_type && (ObFloatType == ob_type || ObDoubleType == ob_type)) { + scale = OB_MIN_NUMBER_SCALE - 1; // binary_float and binar_double scale from oci is 0, need set to -85 + } else if (DBLINK_DRV_OCI == link_type && ObDateTimeType == ob_type) { + scale = 0; + } else if (tmp_scale < OB_MIN_NUMBER_SCALE || tmp_scale > OB_MAX_NUMBER_SCALE) { + scale = OB_MIN_NUMBER_SCALE - 1; // format it to -85 if scale out of range + } else { + scale = tmp_scale; // for a valid scale, just set it + } + + // format length from others to oceanbase + if (ob_is_accuracy_length_valid_tc(ob_type)) { + int32_t max_length = 0; + if (old_max_length) { + max_length = OB_MAX_LONGTEXT_LENGTH_OLD; + } else { + max_length = OB_MAX_LONGTEXT_LENGTH; + } + if (tmp_length < 1 || tmp_length > max_length) { + length = max_length; + } else { + length = tmp_length; + } + } + if (ObDoubleType == ob_type || ObFloatType == ob_type) { + precision = -1; + scale = -1; + length = -1; } } + return ret; } } // end namespace sqlclient diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_result.h b/deps/oblib/src/lib/mysqlclient/ob_mysql_result.h index 5bab4412c6..493554058e 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_result.h +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_result.h @@ -1372,7 +1372,7 @@ public: virtual int get_col_meta(const int64_t col_idx, bool old_max_length, oceanbase::common::ObString &name, ObObjMeta &meta, ObAccuracy &acc) const = 0; - void format_precision_scale_length(int16_t &precision, int16_t &scale, int32_t &length, + int format_precision_scale_length(int16_t &precision, int16_t &scale, int32_t &length, oceanbase::common::ObObjType ob_type, oceanbase::common::ObCollationType cs_type, DblinkDriverProto link_type, bool old_max_length) const; /// @note return OB_SUCCESS instead of OB_ERR_NULL_VALUE when obj is null diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_result_impl.cpp b/deps/oblib/src/lib/mysqlclient/ob_mysql_result_impl.cpp index 809920a45a..b162b0f01a 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_result_impl.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_result_impl.cpp @@ -631,6 +631,7 @@ int ObMySQLResultImpl::get_ob_type(ObObjType &ob_type, obmysql::EMySQLFieldType ob_type = ObInt32Type; break; case obmysql::EMySQLFieldType::MYSQL_TYPE_LONGLONG: + case obmysql::EMySQLFieldType::MYSQL_TYPE_INT24: ob_type = ObIntType; break; case obmysql::EMySQLFieldType::MYSQL_TYPE_FLOAT: @@ -796,7 +797,7 @@ int ObMySQLResultImpl::get_obj(const int64_t col_idx, ObObj &obj, case ObUDoubleType: if (OB_SUCC(get_double(col_idx, obj_value.double_))) { - obj.set_double(obj_value.double_); + obj.set_double(type.get_type(), obj_value.double_); } break; case ObVarcharType: @@ -844,7 +845,7 @@ int ObMySQLResultImpl::get_obj(const int64_t col_idx, ObObj &obj, case ObUFloatType: if (OB_SUCC(get_float(col_idx, obj_value.float_))) { - obj.set_float(obj_value.float_); + obj.set_float(type.get_type(), obj_value.float_); } break; case ObDateTimeType: @@ -854,9 +855,10 @@ int ObMySQLResultImpl::get_obj(const int64_t col_idx, ObObj &obj, } break; case ObTimestampType: - //TODO::need fill available timezone here @zhuweng - if (OB_SUCC(get_timestamp(col_idx, nullptr, obj_value.datetime_))) - { + if (OB_ISNULL(tz_info)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("tz info is NULL", K(ret)); + } else if (OB_SUCC(get_timestamp(col_idx, tz_info, obj_value.datetime_))) { obj.set_timestamp(obj_value.datetime_); } break; @@ -886,6 +888,27 @@ int ObMySQLResultImpl::get_obj(const int64_t col_idx, ObObj &obj, } } break; + case ObDateType: { + if (OB_SUCC(get_date(col_idx, obj_value.date_))) + { + obj.set_date(obj_value.date_); + } + break; + } + case ObTimeType: { + if (OB_SUCC(get_time(col_idx, obj_value.time_))) + { + obj.set_time(obj_value.time_); + } + break; + } + case ObYearType: { + if (OB_SUCC(get_year(col_idx, obj_value.year_))) + { + obj.set_year(obj_value.year_); + } + break; + } case ObIntervalYMType: { ObIntervalYMValue ym_val; if (OB_SUCC(get_interval_ym(col_idx, ym_val))) { @@ -916,9 +939,63 @@ int ObMySQLResultImpl::get_obj(const int64_t col_idx, ObObj &obj, } break; } - case ObDateType: - case ObTimeType: - case ObYearType: + case ObTinyTextType: + case ObTextType: + case ObMediumTextType: + case ObLongTextType: { + if (lib::is_oracle_mode()) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("oracle mode dblink not support lob type", K(ret), K(type.get_type())); + } else if (OB_SUCC(get_varchar(col_idx, obj_str))) { + obj.set_lob_value(type.get_type(), obj_str.ptr(), obj_str.length()); + obj.set_collation_type(type.get_collation_type()); + } + break; + } + case ObEnumType: { + if (OB_SUCC(get_varchar(col_idx, obj_str))) + { + obj.set_enum_inner(obj_str); + obj.set_collation_type(type.get_collation_type()); + } + break; + } + case ObSetType: { + if (OB_SUCC(get_varchar(col_idx, obj_str))) + { + obj.set_set_inner(obj_str); + obj.set_collation_type(type.get_collation_type()); + } + break; + } + case ObGeometryType: { + /* + if (OB_SUCC(get_varchar(col_idx, obj_str))) + { + obj.set_geometry_value(type.get_type(), obj_str.ptr(), obj_str.length()); + + }*/ + ret = OB_NOT_SUPPORTED; + break; + } + case ObJsonType: { + /*if (OB_SUCC(get_varchar(col_idx, obj_str))) + { + obj.set_json_value(type.get_type(), obj_str.ptr(), obj_str.length()); + obj.set_collation_type(type.get_collation_type()); + }*/ + ret = OB_NOT_SUPPORTED; + break; + } + case ObBitType: { + /* + if (OB_SUCC(get_uint(col_idx, obj_value.uint64_)))//ailing to do + { + obj.set_bit(obj_value.uint64_); + }*/ + ret = OB_NOT_SUPPORTED; + break; + } default: ret = OB_NOT_SUPPORTED; LOG_WARN("not supported object type", "obj_type", obj.get_type(), K(ret)); diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_statement.cpp b/deps/oblib/src/lib/mysqlclient/ob_mysql_statement.cpp index 379f1fdb5d..8ef4153474 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_statement.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_statement.cpp @@ -18,6 +18,7 @@ #include "lib/mysqlclient/ob_mysql_statement.h" #include "lib/mysqlclient/ob_server_connection_pool.h" #include "lib/mysqlclient/ob_mysql_connection_pool.h" +#include "lib/mysqlclient/ob_dblink_error_trans.h" namespace oceanbase { @@ -100,15 +101,18 @@ int ObMySQLStatement::execute_update(int64_t &affected_rows) int64_t begin = ObTimeUtility::current_monotonic_raw_time(); if (0 != (tmp_ret = mysql_real_query(stmt_, sql_str_, STRLEN(sql_str_)))) { ret = -mysql_errno(stmt_); - if (is_need_disconnect_error(ret)) { - conn_->set_usable(false); - } LOG_WARN("fail to query server", "sessid", conn_->get_sessid(), "server", stmt_->host, "port", stmt_->port, "err_msg", mysql_error(stmt_), K(tmp_ret), K(ret), K(sql_str_)); if (OB_NOT_MASTER == tmp_ret) { // conn -> server pool -> connection pool conn_->get_root()->get_root()->signal_refresh(); // refresh server pool immediately } + if (OB_INVALID_ID != conn_->get_dblink_id()) { + TRANSLATE_CLIENT_ERR(ret, mysql_error(stmt_)); + } + if (is_need_disconnect_error(ret)) { + conn_->set_usable(false); + } } else { affected_rows = mysql_affected_rows(stmt_); } @@ -135,9 +139,6 @@ ObMySQLResult *ObMySQLStatement::execute_query(bool enable_use_result) int64_t begin = ObTimeUtility::current_monotonic_raw_time(); if (0 != mysql_real_query(stmt_, sql_str_, STRLEN(sql_str_))) { ret = -mysql_errno(stmt_); - if (is_need_disconnect_error(ret)) { - conn_->set_usable(false); - } const int ER_LOCK_WAIT_TIMEOUT = -1205; if (ER_LOCK_WAIT_TIMEOUT == ret) { LOG_INFO("fail to query server", "sessid", conn_->get_sessid(), "host", stmt_->host, "port", stmt_->port, @@ -149,6 +150,11 @@ ObMySQLResult *ObMySQLStatement::execute_query(bool enable_use_result) if (OB_SUCCESS == ret) { ret = OB_ERR_SQL_CLIENT; LOG_WARN("can not get errno", K(ret)); + } else if (OB_INVALID_ID != conn_->get_dblink_id()) { + TRANSLATE_CLIENT_ERR(ret, mysql_error(stmt_)); + } + if (is_need_disconnect_error(ret)) { + conn_->set_usable(false); } } else if (OB_FAIL(result_.init(enable_use_result))) { LOG_WARN("fail to init sql result", K(ret)); @@ -164,11 +170,45 @@ ObMySQLResult *ObMySQLStatement::execute_query(bool enable_use_result) bool ObMySQLStatement::is_need_disconnect_error(int ret) { - const int CR_SERVER_GONE_ERROR = 2006; - const int CR_SERVER_LOST = 2013; - // need disconnect when there is a connection error + bool need_disconnect = false; + + constexpr int CR_UNKNOWN_ERROR = 2000; + constexpr int CR_SOCKET_CREATE_ERROR = 2001; + constexpr int CR_CONNECTION_ERROR = 2002; + constexpr int CR_CONN_HOST_ERROR = 2003; + constexpr int CR_IPSOCK_ERROR = 2004; + constexpr int CR_UNKNOWN_HOST = 2005; + constexpr int CR_SERVER_GONE_ERROR = 2006; + constexpr int CR_WRONG_HOST_INFO = 2009; + constexpr int CR_LOCALHOST_CONNECTION = 2010; + constexpr int CR_TCP_CONNECTION = 2011; + constexpr int CR_SERVER_HANDSHAKE_ERR = 2012; + constexpr int CR_SERVER_LOST = 2013; + constexpr int CR_COMMANDS_OUT_OF_SYNC = 2014; + int obclient_connection_errnos[] = { + CR_UNKNOWN_ERROR, + CR_SOCKET_CREATE_ERROR, + CR_CONNECTION_ERROR, + CR_CONN_HOST_ERROR, + CR_IPSOCK_ERROR, + CR_UNKNOWN_HOST, + CR_SERVER_GONE_ERROR, + CR_WRONG_HOST_INFO, + CR_LOCALHOST_CONNECTION, + CR_TCP_CONNECTION, + CR_SERVER_HANDSHAKE_ERR, + CR_SERVER_LOST, + CR_COMMANDS_OUT_OF_SYNC + }; + ret = abs(ret); - return ret == CR_SERVER_GONE_ERROR || ret == CR_SERVER_LOST; + for (int64_t i = 0; i < sizeof(obclient_connection_errnos) / sizeof(int); ++i) { + if (ret == obclient_connection_errnos[i]) { + need_disconnect = true;// need disconnect when there is a connection error + break; + } + } + return need_disconnect; } } // end namespace sqlclient diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_statement.h b/deps/oblib/src/lib/mysqlclient/ob_mysql_statement.h index 8a9547ed04..1b825a4647 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_statement.h +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_statement.h @@ -50,7 +50,7 @@ public: * but ignore affected_rows */ int execute_update(); - bool is_need_disconnect_error(const int ret); + bool is_need_disconnect_error(int ret); /* * ! Deprecated diff --git a/deps/oblib/src/lib/mysqlclient/ob_server_connection_pool.cpp b/deps/oblib/src/lib/mysqlclient/ob_server_connection_pool.cpp index 4d705fdd18..172e1b477b 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_server_connection_pool.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_server_connection_pool.cpp @@ -33,6 +33,9 @@ ObServerConnectionPool::ObServerConnectionPool() : max_allowed_conn_count_(0), server_not_available_(false) { + db_name_[0] = 0; + db_user_[0] = 0; + db_pass_[0] = 0; } @@ -193,7 +196,8 @@ int ObServerConnectionPool::init_dblink(uint64_t dblink_id, const ObAddr &server if (OB_FAIL(init(root, server, max_allowed_conn_count))) { LOG_WARN("fail to init", K(ret)); } else if (OB_INVALID_ID == dblink_id - || db_tenant.empty() || db_user.empty() || db_pass.empty() /*|| db_name.empty()*/ + || db_tenant.empty() || db_user.empty() || db_pass.empty() + || (!lib::is_oracle_mode() && db_name.empty()) || OB_UNLIKELY(cluster_str.length() >= OB_MAX_CLUSTER_NAME_LENGTH) || OB_UNLIKELY(db_tenant.length() >= OB_MAX_TENANT_NAME_LENGTH) || OB_UNLIKELY(db_user.length() >= OB_MAX_USER_NAME_LENGTH) diff --git a/deps/oblib/src/lib/ob_define.h b/deps/oblib/src/lib/ob_define.h index c01bdaf7d6..302399c926 100644 --- a/deps/oblib/src/lib/ob_define.h +++ b/deps/oblib/src/lib/ob_define.h @@ -258,6 +258,7 @@ const int64_t OB_MAX_WHEN_CONDITION_LENGTH = 4000; // Compatible with Oracle const int64_t OB_MAX_UPDATE_COLUMNS_LENGTH = 4000; // Compatible with Oracle const int64_t OB_MAX_TRIGGER_BODY_LENGTH = 64 * 1024; // In Oracle, it is the LONG type, but there is a problem with the large object type used in the OB internal table. const int64_t OB_MAX_DBLINK_NAME_LENGTH = 128; // Compatible with Oracle +const int64_t OB_MAX_DOMIN_NAME_LENGTH = 240; // max length of domin name, refer to max domin name of oracle const int64_t OB_MAX_QB_NAME_LENGTH = 20; // Compatible with Oracle, hint specifies the length of the maximum qb_name. const int64_t OB_MAX_SEQUENCE_NAME_LENGTH = 128; // Compatible with Oracle, error is reported when the logic is greater than const int64_t OB_MAX_KEYSTORE_NAME_LENGTH = 128; diff --git a/deps/oblib/src/lib/ob_errno.h b/deps/oblib/src/lib/ob_errno.h index 89b4680e3d..2c74c6afd9 100644 --- a/deps/oblib/src/lib/ob_errno.h +++ b/deps/oblib/src/lib/ob_errno.h @@ -254,6 +254,7 @@ constexpr int OB_ERR_OPERATOR_CANNOT_BE_USED_WITH_LIST = -5729; constexpr int OB_INVALID_ROWID = -5802; constexpr int OB_ERR_NUMERIC_NOT_MATCH_FORMAT_LENGTH = -5873; constexpr int OB_ERR_DATETIME_INTERVAL_INTERNAL_ERROR = -5898; +constexpr int OB_ERR_DBLINK_REMOTE_ECODE = -5975; constexpr int OB_ERR_DBLINK_NO_LIB = -5976; constexpr int OB_SWITCHING_TO_FOLLOWER_GRACEFULLY = -6202; constexpr int OB_MASK_SET_NO_NODE = -6203; diff --git a/deps/oblib/src/lib/ob_name_def.h b/deps/oblib/src/lib/ob_name_def.h index 2179a7f77f..463790bed1 100644 --- a/deps/oblib/src/lib/ob_name_def.h +++ b/deps/oblib/src/lib/ob_name_def.h @@ -622,6 +622,7 @@ #define N_COMPRESS_METHOD "compress_method" #define N_JOIN_INFO "join_info" #define N_ID_SET "id_set" +#define N_CURRENT_SCN "current_scn" #define N_EQUAL_SET "equal_set" #define N_LEFT_ID "left_id" #define N_RIGHT_ID "right_id" diff --git a/src/objit/include/objit/common/ob_item_type.h b/src/objit/include/objit/common/ob_item_type.h index fb55163e75..bbe882abf2 100755 --- a/src/objit/include/objit/common/ob_item_type.h +++ b/src/objit/include/objit/common/ob_item_type.h @@ -794,21 +794,21 @@ typedef enum ObItemType T_FUN_SYS_JSON_EXISTS = 1686, T_FUN_SYS_TREAT = 1687, T_NULLX_CLAUSE = 1688, // null clause on json expr - T_WEIGHT_STRING_LEVEL_PARAM = 1689, // `level 1-2` and `level 1,2,3` clause on json expr - T_FUN_SYS_NLS_INITCAP = 1690, - - T_FUN_SYS_MAKEXML = 1691, - T_FUN_SYS_XML_ELEMENT = 1692, - T_FUN_SYS_XMLPARSE = 1693, - T_FUN_ORA_XMLAGG = 1694, - T_FUN_SYS_XML_ATTRIBUTES = 1695, - T_FUN_SYS_XML_EXTRACTVALUE = 1696, - T_FUN_SYS_XML_EXTRACT = 1697, - T_FUN_SYS_XML_SERIALIZE = 1698, - T_FUN_SYS_XMLCAST = 1699, - T_FUN_SYS_XML_ATTRIBUTES_VALUES = 1700, - T_FUN_SYS_UPDATE_XML = 1701, - T_FUN_SYS_PRIV_MAKE_XML_BINARY = 1702, // add only for xml dml rewrite + T_FUN_SYS_NLS_INITCAP = 1689, + T_WEIGHT_STRING_LEVEL_PARAM = 1690, // `level 1-2` and `level 1,2,3` clause on json expr + T_FUN_SYS_CURRENT_SCN = 1691, + T_FUN_SYS_MAKEXML = 1692, + T_FUN_SYS_XML_ELEMENT = 1693, + T_FUN_SYS_XMLPARSE = 1694, + T_FUN_ORA_XMLAGG = 1695, + T_FUN_SYS_XML_ATTRIBUTES = 1696, + T_FUN_SYS_XML_EXTRACTVALUE = 1697, + T_FUN_SYS_XML_EXTRACT = 1698, + T_FUN_SYS_XML_SERIALIZE = 1699, + T_FUN_SYS_XMLCAST = 1700, + T_FUN_SYS_XML_ATTRIBUTES_VALUES = 1701, + T_FUN_SYS_UPDATE_XML = 1702, + T_FUN_SYS_PRIV_MAKE_XML_BINARY = 1703, // add only for xml dml rewrite ///< @note add new oracle only function type before this line T_FUN_SYS_TABLET_AUTOINC_NEXTVAL = 1801, // add only for heap table @@ -1308,6 +1308,7 @@ typedef enum ObItemType T_FLUSH_ILOGCACHE, T_ADMIN_SERVER, T_ADMIN_ZONE, + T_FLASHBACK_READ_TX_UNCOMMITTED, T_CS_DISKMAINTAIN, T_DISK_OP_PARAM, T_CS_ADMIN_PARAMS, diff --git a/src/observer/mysql/ob_mysql_result_set.cpp b/src/observer/mysql/ob_mysql_result_set.cpp index 53b442d068..50e0dcaf55 100644 --- a/src/observer/mysql/ob_mysql_result_set.cpp +++ b/src/observer/mysql/ob_mysql_result_set.cpp @@ -42,7 +42,6 @@ int ObMySQLResultSet::to_mysql_field(const ObField &field, ObMySQLField &mfield) mfield.charsetnr_ = field.charsetnr_; mfield.flags_ = field.flags_; mfield.length_ = field.length_; - // 对于Varchar类,检查charset: mfield.flags_ &= (~BINARY_FLAG); bool is_oracle_lob = false; diff --git a/src/observer/virtual_table/ob_information_user_privileges_table.cpp b/src/observer/virtual_table/ob_information_user_privileges_table.cpp index 9daf7de23c..744a53e4da 100644 --- a/src/observer/virtual_table/ob_information_user_privileges_table.cpp +++ b/src/observer/virtual_table/ob_information_user_privileges_table.cpp @@ -56,6 +56,10 @@ ObInfoSchemaUserPrivilegesTable::StaticInit::StaticInit() "REPLICATION SLAVE"; ObInfoSchemaUserPrivilegesTable::priv_type_strs[OB_PRIV_REPL_CLIENT_SHIFT] = "REPLICATION CLIENT"; + ObInfoSchemaUserPrivilegesTable::priv_type_strs[OB_PRIV_DROP_DATABASE_LINK_SHIFT] = + "DROP DATABASE LINK"; + ObInfoSchemaUserPrivilegesTable::priv_type_strs[OB_PRIV_CREATE_DATABASE_LINK_SHIFT] = + "CREATE DATABASE LINK"; } ObInfoSchemaUserPrivilegesTable::ObInfoSchemaUserPrivilegesTable() diff --git a/src/observer/virtual_table/ob_mysql_user_table.cpp b/src/observer/virtual_table/ob_mysql_user_table.cpp index 1e55b097e7..c6fa902b87 100644 --- a/src/observer/virtual_table/ob_mysql_user_table.cpp +++ b/src/observer/virtual_table/ob_mysql_user_table.cpp @@ -138,6 +138,8 @@ int ObMySQLUserTable::inner_get_next_row(common::ObNewRow *&row) NO_EXIST_PRIV_CASE(EXECUTE); EXIST_PRIV_CASE(REPL_SLAVE); EXIST_PRIV_CASE(REPL_CLIENT); + EXIST_PRIV_CASE(DROP_DATABASE_LINK); + EXIST_PRIV_CASE(CREATE_DATABASE_LINK); EXIST_PRIV_CASE(CREATE_VIEW); EXIST_PRIV_CASE(SHOW_VIEW); NO_EXIST_PRIV_CASE(CREATE_ROUTINE); diff --git a/src/observer/virtual_table/ob_mysql_user_table.h b/src/observer/virtual_table/ob_mysql_user_table.h index af1eaf84c3..27fefd4c74 100644 --- a/src/observer/virtual_table/ob_mysql_user_table.h +++ b/src/observer/virtual_table/ob_mysql_user_table.h @@ -71,6 +71,8 @@ private: AUTHENTICATION_STRING, PASSWORD_EXPIRED, ACCOUNT_LOCKED, + DROP_DATABASE_LINK_PRIV, + CREATE_DATABASE_LINK_PRIV, }; public: ObMySQLUserTable(); diff --git a/src/observer/virtual_table/ob_show_grants.cpp b/src/observer/virtual_table/ob_show_grants.cpp index 9e296ed15c..8addf1d003 100644 --- a/src/observer/virtual_table/ob_show_grants.cpp +++ b/src/observer/virtual_table/ob_show_grants.cpp @@ -544,6 +544,12 @@ int ObShowGrants::print_privs_to_buff( if ((priv_set & OB_PRIV_REPL_CLIENT) && OB_SUCCESS == ret) { ret = BUF_PRINTF(" REPLICATION CLIENT,"); } + if ((priv_set & OB_PRIV_DROP_DATABASE_LINK) && OB_SUCCESS == ret) { + ret = BUF_PRINTF(" DROP DATABASE LINK,"); + } + if ((priv_set & OB_PRIV_CREATE_DATABASE_LINK) && OB_SUCCESS == ret) { + ret = BUF_PRINTF(" CREATE DATABASE LINK,"); + } if (OB_SUCCESS == ret && pos > 0) { pos--; //Delete last ',' } diff --git a/src/rootserver/ob_ddl_operator.cpp b/src/rootserver/ob_ddl_operator.cpp index eb4f3ab97b..f36b496d91 100644 --- a/src/rootserver/ob_ddl_operator.cpp +++ b/src/rootserver/ob_ddl_operator.cpp @@ -6643,6 +6643,7 @@ int ObDDLOperator::grant_revoke_user( const uint64_t user_id, const ObPrivSet priv_set, const bool grant, + const bool is_from_inner_sql, const ObString *ddl_stmt_str, common::ObMySQLTransaction &trans) { @@ -6679,7 +6680,7 @@ int ObDDLOperator::grant_revoke_user( if (OB_FAIL(schema_service_.gen_new_schema_version(tenant_id, new_schema_version))) { LOG_WARN("fail to gen new schema_version", K(ret), K(tenant_id)); } else if (OB_FAIL(schema_sql_service->get_user_sql_service().grant_revoke_user( - new_user_info, new_schema_version, ddl_stmt_str, trans))) { + new_user_info, new_schema_version, ddl_stmt_str, trans, is_from_inner_sql))) { LOG_WARN("Failed to grant or revoke user", K(tenant_id), K(user_id), K(grant), K(ret)); } } diff --git a/src/rootserver/ob_ddl_operator.h b/src/rootserver/ob_ddl_operator.h index 575ce97a80..9de676c140 100644 --- a/src/rootserver/ob_ddl_operator.h +++ b/src/rootserver/ob_ddl_operator.h @@ -584,6 +584,7 @@ public: const uint64_t user_id, const ObPrivSet priv_set, const bool grant, + const bool is_from_inner_sql, const common::ObString *ddl_stmt_str, common::ObMySQLTransaction &trans); virtual int lock_user(const uint64_t tenant_id, diff --git a/src/rootserver/ob_ddl_service.cpp b/src/rootserver/ob_ddl_service.cpp index 7e31076682..6ec1fd6c08 100644 --- a/src/rootserver/ob_ddl_service.cpp +++ b/src/rootserver/ob_ddl_service.cpp @@ -25917,6 +25917,7 @@ int ObDDLService::grant_table_and_col_privs_to_user( need_priv, arg.obj_priv_array_, arg.option_, + false, obj_priv_key, schema_guard)); /* 2. deal with cols privs */ @@ -25940,6 +25941,7 @@ int ObDDLService::grant_table_and_col_privs_to_user( need_priv, obj_priv_array, arg.option_, + false, obj_priv_key, schema_guard)); } @@ -25960,6 +25962,7 @@ int ObDDLService::grant_table_and_col_privs_to_user( need_priv, obj_priv_array, arg.option_, + false, obj_priv_key, schema_guard)); } @@ -25980,6 +25983,7 @@ int ObDDLService::grant_table_and_col_privs_to_user( need_priv, obj_priv_array, arg.option_, + false, obj_priv_key, schema_guard)); } @@ -26286,6 +26290,7 @@ int ObDDLService::grant(const ObGrantArg &arg) need_priv, arg.obj_priv_array_, arg.option_, + arg.is_inner_, obj_priv_key, schema_guard))) { LOG_WARN("Grant priv to user failed", K(ret)); @@ -26398,7 +26403,9 @@ int ObDDLService::revoke(const ObRevokeUserArg &arg) LOG_WARN("gen user_priv sql failed", K(arg), K(ret)); } else if (FALSE_IT(ddl_sql = ddl_stmt_str.string())) { } else if (OB_FAIL(grant_revoke_user(arg.tenant_id_, arg.user_id_, - arg.priv_set_, grant, &ddl_sql, + arg.priv_set_, grant, + false, + &ddl_sql, schema_guard))) { LOG_WARN("Revoke user failed", K(arg), K(grant), K(ret)); } @@ -26419,6 +26426,7 @@ int ObDDLService::grant_priv_to_user(const uint64_t tenant_id, const ObNeedPriv &need_priv, const share::ObRawObjPrivArray &obj_priv_array, const uint64_t option, + const bool is_from_inner_sql, ObObjPrivSortKey &obj_priv_key, share::schema::ObSchemaGetterGuard &schema_guard) { @@ -26438,7 +26446,7 @@ int ObDDLService::grant_priv_to_user(const uint64_t tenant_id, LOG_WARN("gen user_priv sql failed", K(ret), K(user_name), K(host_name)); } else if (FALSE_IT(ddl_sql = ddl_stmt_str.string())) { } else if (OB_FAIL(grant_revoke_user(tenant_id, user_id, need_priv.priv_set_, - true, &ddl_sql, schema_guard))) { + true, is_from_inner_sql, &ddl_sql, schema_guard))) { LOG_WARN("Grant user error", KR(ret), K(tenant_id), K(user_id), K(ddl_sql), K(need_priv)); } break; @@ -26510,7 +26518,7 @@ int ObDDLService::revoke_all( } else if (FALSE_IT(ddl_sql = ddl_stmt_str.string())) { } else if (OB_FAIL(ddl_operator.grant_revoke_user(tenant_id, user_id, OB_PRIV_ALL|OB_PRIV_GRANT, - false, &ddl_sql, trans))) { + false, false, &ddl_sql, trans))) { LOG_WARN("Revoke user error", K(ret)); } else if (OB_FAIL(ddl_operator.drop_db_table_privs(tenant_id, user_id, trans))) { LOG_WARN("Drop db table priv error", K(ret)); @@ -26539,6 +26547,7 @@ int ObDDLService::grant_revoke_user( const uint64_t user_id, const ObPrivSet priv_set, const bool grant, + const bool is_from_inner_sql, const ObString *ddl_stmt_str, share::schema::ObSchemaGetterGuard &schema_guard) { @@ -26557,7 +26566,7 @@ int ObDDLService::grant_revoke_user( LOG_WARN("Start transaction failed", KR(ret), K(tenant_id), K(refreshed_schema_version)); } else { ObDDLOperator ddl_operator(*schema_service_, *sql_proxy_); - if (OB_FAIL(ddl_operator.grant_revoke_user(tenant_id, user_id, priv_set, grant, ddl_stmt_str, trans))) { + if (OB_FAIL(ddl_operator.grant_revoke_user(tenant_id, user_id, priv_set, grant, is_from_inner_sql, ddl_stmt_str, trans))) { LOG_WARN("fail to grant revoke user", K(ret), K(tenant_id), K(user_id), K(priv_set), K(grant)); } if (trans.is_started()) { @@ -27990,8 +27999,12 @@ int ObDDLService::create_dblink(const obrpc::ObCreateDbLinkArg &arg, const ObStr } else if (OB_FAIL(schema_guard.check_dblink_exist(tenant_id, dblink_name, is_exist))) { LOG_WARN("failed to check dblink exist", K(ret), K(dblink_info)); } else if (is_exist) { - ret = OB_OBJ_ALREADY_EXIST; - LOG_WARN("dblink already exist", K(ret), K(dblink_info.get_dblink_name())); + if (arg.dblink_info_.get_if_not_exist()) { + // do nothing + } else { + ret = OB_OBJ_ALREADY_EXIST; + LOG_WARN("dblink already exist", K(ret), K(dblink_info.get_dblink_name())); + } } else { ObDDLSQLTransaction trans(schema_service_); ObDDLOperator ddl_operator(*schema_service_, *sql_proxy_); @@ -28034,8 +28047,13 @@ int ObDDLService::drop_dblink(const obrpc::ObDropDbLinkArg &arg, const ObString } else if (OB_FAIL(schema_guard.get_dblink_schema(tenant_id, dblink_name, dblink_schema))) { LOG_WARN("failed to get dblink schema", K(ret), K(tenant_id), K(dblink_name)); } else if (OB_ISNULL(dblink_schema)) { - ret = OB_DBLINK_NOT_EXIST_TO_DROP; - LOG_WARN("dblink not exist", K(ret), K(tenant_id), K(dblink_name)); + if (arg.if_exist_) { + // do nothing + LOG_WARN("loglcq dblink not exist", K(ret), K(tenant_id), K(dblink_name)); + } else { + ret = OB_DBLINK_NOT_EXIST_TO_DROP; + LOG_WARN("dblink not exist", K(ret), K(tenant_id), K(dblink_name)); + } } else { ObDDLSQLTransaction trans(schema_service_); ObDDLOperator ddl_operator(*schema_service_, *sql_proxy_); diff --git a/src/rootserver/ob_ddl_service.h b/src/rootserver/ob_ddl_service.h index f79a9d60dd..b25250cf41 100644 --- a/src/rootserver/ob_ddl_service.h +++ b/src/rootserver/ob_ddl_service.h @@ -735,6 +735,7 @@ int check_table_udt_id_is_exist(share::schema::ObSchemaGetterGuard &schema_guard const share::schema::ObNeedPriv &need_priv, const share::ObRawObjPrivArray &obj_priv_array, const uint64_t option, + const bool is_from_inner_sql, share::schema::ObObjPrivSortKey &obj_priv_key, share::schema::ObSchemaGetterGuard &schema_guard); virtual int grant_table_and_col_privs_to_user( @@ -748,6 +749,7 @@ int check_table_udt_id_is_exist(share::schema::ObSchemaGetterGuard &schema_guard const uint64_t user_id, const ObPrivSet priv_set, const bool grant, + const bool is_from_inner_sql, const common::ObString *ddl_stmt_str, share::schema::ObSchemaGetterGuard &schema_guard); diff --git a/src/rootserver/ob_ddl_sql_generator.cpp b/src/rootserver/ob_ddl_sql_generator.cpp index f6aae2f1f1..61cdabb9c4 100644 --- a/src/rootserver/ob_ddl_sql_generator.cpp +++ b/src/rootserver/ob_ddl_sql_generator.cpp @@ -101,6 +101,10 @@ int ObDDLSqlGenerator::get_priv_name(const int64_t priv, const char *&name) name = "REPLICATION SLAVE"; break; case OB_PRIV_REPL_CLIENT: name = "REPLICATION CLIENT"; break; + case OB_PRIV_DROP_DATABASE_LINK: + name = "DROP DATABASE LINK"; break; + case OB_PRIV_CREATE_DATABASE_LINK: + name = "CREATE DATABASE LINK"; break; default: { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid priv", K(ret), K(priv)); diff --git a/src/share/gen_errno.pl b/src/share/gen_errno.pl index 9b7f0959a0..6b662a20e7 100755 --- a/src/share/gen_errno.pl +++ b/src/share/gen_errno.pl @@ -592,6 +592,26 @@ inline const _error *get_error(int index) return _errors[index]; } +int get_oracle_errno(int index) +{ + return get_error(index)->oracle_errno; +} + +int get_mysql_errno(int index) +{ + return get_error(index)->mysql_errno; +} + +const char* get_oracle_str_error(int index) +{ + return get_error(index)->oracle_str_error; +} + +const char* get_mysql_str_error(int index) +{ + return get_error(index)->str_error; +} + namespace oceanbase { namespace common @@ -715,57 +735,6 @@ print $fh_cpp ' } return ret; } -#ifndef __ERROR_CODE_PARSER_ - int get_ob_errno_from_oracle_errno(const int error_no, const char *error_msg, int &ob_errno) { - const int orcl_errno = abs(error_no); - ob_errno = error_no; - int64_t edit_dist = 0x7fffffffffffffff; - int64_t min_edit_dist = 0x7fffffffffffffff; - if (-4016 == error_no || // error_no mayby oceanbase inner errro number sometimes, need skip it - -4013 == error_no || - -4012 == error_no || - -4007 == error_no || - -4002 == error_no) { - } else if (-2013 == error_no || // error_no mayby mysql inner errro number sometimes - -2006 == error_no) { - ob_errno = OB_ERR_UNEXPECTED; - LOG_USER_ERROR(OB_ERR_UNEXPECTED, "local server\'s dblink can not connect to remote sever by mysqlclient(interal error code: 2006 or 2013)"); - } else if (nullptr == error_msg) { // error_no maybe oracle inner error number at most times. - for (int i = 0; i < OB_MAX_ERROR_CODE; ++i) { - if (orcl_errno == get_error(i)->oracle_errno) { - ob_errno = -i; - break; - } - } - } else { - ObEditDistance ed; - for (int i = 0; i < OB_MAX_ERROR_CODE; ++i) { - if (orcl_errno == get_error(i)->oracle_errno) { - const char *orcl_str_error = get_error(i)->oracle_str_user_error; - if (nullptr == orcl_str_error) { - // In the case of a null pointer boundary, - // the reason for setting edit_distance to 0x7ffffffffffffffe is to deal with the situation where - // error_msg does not match ORACLE_STR_USER_ERROR[i] but orcl_errno == ORACLE_ERRNO[i]. - edit_dist = 0x7ffffffffffffffe; - } else { - // The edit distance between the strings is used to measure their similarity. - // The smaller the edit distance, the greater the similarity, so as to find the most similar error message. - ObEditDistance::cal_edit_distance(error_msg, orcl_str_error, STRLEN(error_msg), STRLEN(orcl_str_error), edit_dist); - } - if (edit_dist < min_edit_dist) { - ob_errno = -i; - min_edit_dist = edit_dist; - if (0 == min_edit_dist) { - break; - } - } - } - } - } - LOG_TRACE("trace the ob_errno and oracle_errno.", K(ob_errno), K(error_no), K(min_edit_dist)); - return OB_SUCCESS; - } -#endif int ob_oracle_errno(const int err) { int ret = -1; diff --git a/src/share/inner_table/ob_inner_table_schema.101_150.cpp b/src/share/inner_table/ob_inner_table_schema.101_150.cpp index 359e4a54e7..4ca3ae668f 100644 --- a/src/share/inner_table/ob_inner_table_schema.101_150.cpp +++ b/src/share/inner_table/ob_inner_table_schema.101_150.cpp @@ -818,6 +818,44 @@ int ObInnerTableSchema::all_user_schema(ObTableSchema &table_schema) priv_repl_client_default, priv_repl_client_default); //default_value } + + if (OB_SUCC(ret)) { + ObObj priv_drop_database_link_default; + priv_drop_database_link_default.set_int(0); + ADD_COLUMN_SCHEMA_T("priv_drop_database_link", //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 + priv_drop_database_link_default, + priv_drop_database_link_default); //default_value + } + + if (OB_SUCC(ret)) { + ObObj priv_create_database_link_default; + priv_create_database_link_default.set_int(0); + ADD_COLUMN_SCHEMA_T("priv_create_database_link", //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 + priv_create_database_link_default, + priv_create_database_link_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); @@ -1654,6 +1692,44 @@ int ObInnerTableSchema::all_user_history_schema(ObTableSchema &table_schema) priv_repl_client_default, priv_repl_client_default); //default_value } + + if (OB_SUCC(ret)) { + ObObj priv_drop_database_link_default; + priv_drop_database_link_default.set_int(0); + ADD_COLUMN_SCHEMA_T("priv_drop_database_link", //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 + priv_drop_database_link_default, + priv_drop_database_link_default); //default_value + } + + if (OB_SUCC(ret)) { + ObObj priv_create_database_link_default; + priv_create_database_link_default.set_int(0); + ADD_COLUMN_SCHEMA_T("priv_create_database_link", //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 + priv_create_database_link_default, + priv_create_database_link_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); diff --git a/src/share/inner_table/ob_inner_table_schema.12001_12050.cpp b/src/share/inner_table/ob_inner_table_schema.12001_12050.cpp index 48c3233e0b..8fa06b027b 100644 --- a/src/share/inner_table/ob_inner_table_schema.12001_12050.cpp +++ b/src/share/inner_table/ob_inner_table_schema.12001_12050.cpp @@ -996,6 +996,36 @@ int ObInnerTableSchema::user_schema(ObTableSchema &table_schema) false, //is_nullable false); //is_autoincrement } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("drop_database_link_priv", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + 1, //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("create_database_link_priv", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + 1, //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } table_schema.set_index_using_type(USING_HASH); table_schema.set_row_store_type(ENCODING_ROW_STORE); table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); diff --git a/src/share/inner_table/ob_inner_table_schema.12051_12100.cpp b/src/share/inner_table/ob_inner_table_schema.12051_12100.cpp index 16b61cad57..5b4e0f36ad 100644 --- a/src/share/inner_table/ob_inner_table_schema.12051_12100.cpp +++ b/src/share/inner_table/ob_inner_table_schema.12051_12100.cpp @@ -15031,6 +15031,44 @@ int ObInnerTableSchema::all_virtual_user_schema(ObTableSchema &table_schema) priv_repl_client_default, priv_repl_client_default); //default_value } + + if (OB_SUCC(ret)) { + ObObj priv_drop_database_link_default; + priv_drop_database_link_default.set_int(0); + ADD_COLUMN_SCHEMA_T("priv_drop_database_link", //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 + priv_drop_database_link_default, + priv_drop_database_link_default); //default_value + } + + if (OB_SUCC(ret)) { + ObObj priv_create_database_link_default; + priv_create_database_link_default.set_int(0); + ADD_COLUMN_SCHEMA_T("priv_create_database_link", //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 + priv_create_database_link_default, + priv_create_database_link_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); @@ -15851,6 +15889,44 @@ int ObInnerTableSchema::all_virtual_user_history_schema(ObTableSchema &table_sch priv_repl_client_default, priv_repl_client_default); //default_value } + + if (OB_SUCC(ret)) { + ObObj priv_drop_database_link_default; + priv_drop_database_link_default.set_int(0); + ADD_COLUMN_SCHEMA_T("priv_drop_database_link", //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 + priv_drop_database_link_default, + priv_drop_database_link_default); //default_value + } + + if (OB_SUCC(ret)) { + ObObj priv_create_database_link_default; + priv_create_database_link_default.set_int(0); + ADD_COLUMN_SCHEMA_T("priv_create_database_link", //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 + priv_create_database_link_default, + priv_create_database_link_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); diff --git a/src/share/inner_table/ob_inner_table_schema.12101_12150.cpp b/src/share/inner_table/ob_inner_table_schema.12101_12150.cpp index d51fdfbae1..8f2ebb7d89 100644 --- a/src/share/inner_table/ob_inner_table_schema.12101_12150.cpp +++ b/src/share/inner_table/ob_inner_table_schema.12101_12150.cpp @@ -5825,7 +5825,7 @@ int ObInnerTableSchema::all_virtual_dblink_schema(ObTableSchema &table_schema) 0, //part_key_pos ObVarcharType, //column_type CS_TYPE_INVALID, //column_collation_type - MAX_IP_ADDR_LENGTH, //column_length + OB_MAX_DOMIN_NAME_LENGTH, //column_length -1, //column_precision -1, //column_scale false, //is_nullable @@ -6163,6 +6163,21 @@ int ObInnerTableSchema::all_virtual_dblink_schema(ObTableSchema &table_schema) true, //is_nullable false); //is_autoincrement } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("database_name", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + OB_MAX_DATABASE_NAME_LENGTH, //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } 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); @@ -6338,7 +6353,7 @@ int ObInnerTableSchema::all_virtual_dblink_history_schema(ObTableSchema &table_s 0, //part_key_pos ObVarcharType, //column_type CS_TYPE_INVALID, //column_collation_type - MAX_IP_ADDR_LENGTH, //column_length + OB_MAX_DOMIN_NAME_LENGTH, //column_length -1, //column_precision -1, //column_scale true, //is_nullable @@ -6676,6 +6691,21 @@ int ObInnerTableSchema::all_virtual_dblink_history_schema(ObTableSchema &table_s true, //is_nullable false); //is_autoincrement } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("database_name", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + OB_MAX_DATABASE_NAME_LENGTH, //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } 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); diff --git a/src/share/inner_table/ob_inner_table_schema.15101_15150.cpp b/src/share/inner_table/ob_inner_table_schema.15101_15150.cpp index 340702a6d0..e2c19fce73 100644 --- a/src/share/inner_table/ob_inner_table_schema.15101_15150.cpp +++ b/src/share/inner_table/ob_inner_table_schema.15101_15150.cpp @@ -9404,6 +9404,36 @@ int ObInnerTableSchema::all_virtual_user_real_agent_ora_schema(ObTableSchema &ta false); //is_autoincrement } + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("PRIV_DROP_DATABASE_LINK", //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("PRIV_CREATE_DATABASE_LINK", //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 diff --git a/src/share/inner_table/ob_inner_table_schema.15151_15200.cpp b/src/share/inner_table/ob_inner_table_schema.15151_15200.cpp index 923363cb55..f7b1d91871 100644 --- a/src/share/inner_table/ob_inner_table_schema.15151_15200.cpp +++ b/src/share/inner_table/ob_inner_table_schema.15151_15200.cpp @@ -3685,7 +3685,7 @@ int ObInnerTableSchema::all_virtual_dblink_real_agent_ora_schema(ObTableSchema & 0, //part_key_pos ObVarcharType, //column_type CS_TYPE_UTF8MB4_BIN, //column_collation_type - MAX_IP_ADDR_LENGTH, //column_length + OB_MAX_DOMIN_NAME_LENGTH, //column_length 2, //column_precision -1, //column_scale false, //is_nullable @@ -3992,6 +3992,21 @@ int ObInnerTableSchema::all_virtual_dblink_real_agent_ora_schema(ObTableSchema & false); //is_autoincrement } + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("DATABASE_NAME", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_UTF8MB4_BIN, //column_collation_type + OB_MAX_DATABASE_NAME_LENGTH, //column_length + 2, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + if (OB_SUCC(ret)) { ADD_COLUMN_SCHEMA("GMT_CREATE", //column_name ++column_id, //column_id diff --git a/src/share/inner_table/ob_inner_table_schema.201_250.cpp b/src/share/inner_table/ob_inner_table_schema.201_250.cpp index ad20b4e0ab..dbbf183f4f 100644 --- a/src/share/inner_table/ob_inner_table_schema.201_250.cpp +++ b/src/share/inner_table/ob_inner_table_schema.201_250.cpp @@ -4730,7 +4730,7 @@ int ObInnerTableSchema::all_dblink_schema(ObTableSchema &table_schema) 0, //part_key_pos ObVarcharType, //column_type CS_TYPE_INVALID, //column_collation_type - MAX_IP_ADDR_LENGTH, //column_length + OB_MAX_DOMIN_NAME_LENGTH, //column_length -1, //column_precision -1, //column_scale false, //is_nullable @@ -5068,6 +5068,21 @@ int ObInnerTableSchema::all_dblink_schema(ObTableSchema &table_schema) true, //is_nullable false); //is_autoincrement } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("database_name", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + OB_MAX_DATABASE_NAME_LENGTH, //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } 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); @@ -5259,7 +5274,7 @@ int ObInnerTableSchema::all_dblink_history_schema(ObTableSchema &table_schema) 0, //part_key_pos ObVarcharType, //column_type CS_TYPE_INVALID, //column_collation_type - MAX_IP_ADDR_LENGTH, //column_length + OB_MAX_DOMIN_NAME_LENGTH, //column_length -1, //column_precision -1, //column_scale true, //is_nullable @@ -5597,6 +5612,21 @@ int ObInnerTableSchema::all_dblink_history_schema(ObTableSchema &table_schema) true, //is_nullable false); //is_autoincrement } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("database_name", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + OB_MAX_DATABASE_NAME_LENGTH, //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } 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); diff --git a/src/share/inner_table/ob_inner_table_schema.21301_21350.cpp b/src/share/inner_table/ob_inner_table_schema.21301_21350.cpp index 91b827c831..4db84cca5d 100644 --- a/src/share/inner_table/ob_inner_table_schema.21301_21350.cpp +++ b/src/share/inner_table/ob_inner_table_schema.21301_21350.cpp @@ -1367,7 +1367,7 @@ int ObInnerTableSchema::dba_ob_users_schema(ObTableSchema &table_schema) table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); if (OB_SUCC(ret)) { - if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT USER_NAME, HOST, PASSWD, INFO, (CASE WHEN PRIV_ALTER = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_ALTER, (CASE WHEN PRIV_CREATE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE, (CASE WHEN PRIV_DELETE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_DELETE, (CASE WHEN PRIV_DROP = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_DROP, (CASE WHEN PRIV_GRANT_OPTION = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_GRANT_OPTION, (CASE WHEN PRIV_INSERT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_INSERT, (CASE WHEN PRIV_UPDATE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_UPDATE, (CASE WHEN PRIV_SELECT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SELECT, (CASE WHEN PRIV_INDEX = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_INDEX, (CASE WHEN PRIV_CREATE_VIEW = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_VIEW, (CASE WHEN PRIV_SHOW_VIEW = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SHOW_VIEW, (CASE WHEN PRIV_SHOW_DB = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SHOW_DB, (CASE WHEN PRIV_CREATE_USER = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_USER, (CASE WHEN PRIV_SUPER = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SUPER, (CASE WHEN IS_LOCKED = 0 THEN 'NO' ELSE 'YES' END) AS IS_LOCKED, (CASE WHEN PRIV_PROCESS = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_PROCESS, (CASE WHEN PRIV_CREATE_SYNONYM = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_SYNONYM, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, (CASE WHEN TYPE = 0 THEN 'USER' ELSE 'ROLE' END) AS TYPE, PROFILE_ID, PASSWORD_LAST_CHANGED, (CASE WHEN PRIV_FILE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_FILE, (CASE WHEN PRIV_ALTER_TENANT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_ALTER_TENANT, (CASE WHEN PRIV_ALTER_SYSTEM = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_ALTER_SYSTEM, (CASE WHEN PRIV_CREATE_RESOURCE_POOL = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_RESOURCE_POOL, (CASE WHEN PRIV_CREATE_RESOURCE_UNIT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_RESOURCE_UNIT, MAX_CONNECTIONS, MAX_USER_CONNECTIONS, (CASE WHEN PRIV_REPL_SLAVE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_SLAVE, (CASE WHEN PRIV_REPL_CLIENT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_CLIENT FROM OCEANBASE.__all_user; )__"))) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT USER_NAME, HOST, PASSWD, INFO, (CASE WHEN PRIV_ALTER = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_ALTER, (CASE WHEN PRIV_CREATE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE, (CASE WHEN PRIV_DELETE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_DELETE, (CASE WHEN PRIV_DROP = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_DROP, (CASE WHEN PRIV_GRANT_OPTION = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_GRANT_OPTION, (CASE WHEN PRIV_INSERT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_INSERT, (CASE WHEN PRIV_UPDATE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_UPDATE, (CASE WHEN PRIV_SELECT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SELECT, (CASE WHEN PRIV_INDEX = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_INDEX, (CASE WHEN PRIV_CREATE_VIEW = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_VIEW, (CASE WHEN PRIV_SHOW_VIEW = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SHOW_VIEW, (CASE WHEN PRIV_SHOW_DB = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SHOW_DB, (CASE WHEN PRIV_CREATE_USER = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_USER, (CASE WHEN PRIV_SUPER = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SUPER, (CASE WHEN IS_LOCKED = 0 THEN 'NO' ELSE 'YES' END) AS IS_LOCKED, (CASE WHEN PRIV_PROCESS = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_PROCESS, (CASE WHEN PRIV_CREATE_SYNONYM = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_SYNONYM, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, (CASE WHEN TYPE = 0 THEN 'USER' ELSE 'ROLE' END) AS TYPE, PROFILE_ID, PASSWORD_LAST_CHANGED, (CASE WHEN PRIV_FILE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_FILE, (CASE WHEN PRIV_ALTER_TENANT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_ALTER_TENANT, (CASE WHEN PRIV_ALTER_SYSTEM = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_ALTER_SYSTEM, (CASE WHEN PRIV_CREATE_RESOURCE_POOL = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_RESOURCE_POOL, (CASE WHEN PRIV_CREATE_RESOURCE_UNIT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_RESOURCE_UNIT, MAX_CONNECTIONS, MAX_USER_CONNECTIONS, (CASE WHEN PRIV_REPL_SLAVE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_SLAVE, (CASE WHEN PRIV_REPL_CLIENT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_CLIENT, (CASE WHEN PRIV_DROP_DATABASE_LINK = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_DROP_DATABASE_LINK, (CASE WHEN PRIV_CREATE_DATABASE_LINK = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_DATABASE_LINK FROM OCEANBASE.__all_user; )__"))) { LOG_ERROR("fail to set view_definition", K(ret)); } } @@ -1417,7 +1417,7 @@ int ObInnerTableSchema::cdb_ob_users_schema(ObTableSchema &table_schema) table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); if (OB_SUCC(ret)) { - if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT TENANT_ID, USER_NAME, HOST, PASSWD, INFO, (CASE WHEN PRIV_ALTER = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_ALTER, (CASE WHEN PRIV_CREATE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE, (CASE WHEN PRIV_DELETE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_DELETE, (CASE WHEN PRIV_DROP = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_DROP, (CASE WHEN PRIV_GRANT_OPTION = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_GRANT_OPTION, (CASE WHEN PRIV_INSERT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_INSERT, (CASE WHEN PRIV_UPDATE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_UPDATE, (CASE WHEN PRIV_SELECT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SELECT, (CASE WHEN PRIV_INDEX = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_INDEX, (CASE WHEN PRIV_CREATE_VIEW = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_VIEW, (CASE WHEN PRIV_SHOW_VIEW = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SHOW_VIEW, (CASE WHEN PRIV_SHOW_DB = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SHOW_DB, (CASE WHEN PRIV_CREATE_USER = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_USER, (CASE WHEN PRIV_SUPER = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SUPER, (CASE WHEN IS_LOCKED = 0 THEN 'NO' ELSE 'YES' END) AS IS_LOCKED, (CASE WHEN PRIV_PROCESS = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_PROCESS, (CASE WHEN PRIV_CREATE_SYNONYM = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_SYNONYM, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, (CASE WHEN TYPE = 0 THEN 'USER' ELSE 'ROLE' END) AS TYPE, PROFILE_ID, PASSWORD_LAST_CHANGED, (CASE WHEN PRIV_FILE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_FILE, (CASE WHEN PRIV_ALTER_TENANT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_ALTER_TENANT, (CASE WHEN PRIV_ALTER_SYSTEM = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_ALTER_SYSTEM, (CASE WHEN PRIV_CREATE_RESOURCE_POOL = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_RESOURCE_POOL, (CASE WHEN PRIV_CREATE_RESOURCE_UNIT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_RESOURCE_UNIT, MAX_CONNECTIONS, MAX_USER_CONNECTIONS, (CASE WHEN PRIV_REPL_SLAVE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_SLAVE, (CASE WHEN PRIV_REPL_CLIENT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_CLIENT FROM OCEANBASE.__all_virtual_user; )__"))) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT TENANT_ID, USER_NAME, HOST, PASSWD, INFO, (CASE WHEN PRIV_ALTER = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_ALTER, (CASE WHEN PRIV_CREATE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE, (CASE WHEN PRIV_DELETE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_DELETE, (CASE WHEN PRIV_DROP = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_DROP, (CASE WHEN PRIV_GRANT_OPTION = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_GRANT_OPTION, (CASE WHEN PRIV_INSERT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_INSERT, (CASE WHEN PRIV_UPDATE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_UPDATE, (CASE WHEN PRIV_SELECT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SELECT, (CASE WHEN PRIV_INDEX = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_INDEX, (CASE WHEN PRIV_CREATE_VIEW = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_VIEW, (CASE WHEN PRIV_SHOW_VIEW = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SHOW_VIEW, (CASE WHEN PRIV_SHOW_DB = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SHOW_DB, (CASE WHEN PRIV_CREATE_USER = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_USER, (CASE WHEN PRIV_SUPER = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_SUPER, (CASE WHEN IS_LOCKED = 0 THEN 'NO' ELSE 'YES' END) AS IS_LOCKED, (CASE WHEN PRIV_PROCESS = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_PROCESS, (CASE WHEN PRIV_CREATE_SYNONYM = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_SYNONYM, SSL_TYPE, SSL_CIPHER, X509_ISSUER, X509_SUBJECT, (CASE WHEN TYPE = 0 THEN 'USER' ELSE 'ROLE' END) AS TYPE, PROFILE_ID, PASSWORD_LAST_CHANGED, (CASE WHEN PRIV_FILE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_FILE, (CASE WHEN PRIV_ALTER_TENANT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_ALTER_TENANT, (CASE WHEN PRIV_ALTER_SYSTEM = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_ALTER_SYSTEM, (CASE WHEN PRIV_CREATE_RESOURCE_POOL = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_RESOURCE_POOL, (CASE WHEN PRIV_CREATE_RESOURCE_UNIT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_RESOURCE_UNIT, MAX_CONNECTIONS, MAX_USER_CONNECTIONS, (CASE WHEN PRIV_REPL_SLAVE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_SLAVE, (CASE WHEN PRIV_REPL_CLIENT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_CLIENT, (CASE WHEN PRIV_DROP_DATABASE_LINK = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_DROP_DATABASE_LINK, (CASE WHEN PRIV_CREATE_DATABASE_LINK = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_DATABASE_LINK FROM OCEANBASE.__all_virtual_user; )__"))) { LOG_ERROR("fail to set view_definition", K(ret)); } } @@ -1867,7 +1867,7 @@ int ObInnerTableSchema::user_privileges_schema(ObTableSchema &table_schema) table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); if (OB_SUCC(ret)) { - if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT CAST(CONCAT('''', V.USER_NAME, '''', '@', '''', V.HOST, '''') AS CHAR(81)) AS GRANTEE , CAST('def' AS CHAR(512)) AS TABLE_CATALOG , CAST(V.PRIVILEGE_TYPE AS CHAR(64)) AS PRIVILEGE_TYPE , CAST(V.IS_GRANTABLE AS CHAR(3)) AS IS_GRANTABLE FROM (SELECT U.USER_NAME AS USER_NAME, U.HOST AS HOST, CASE WHEN V1.C1 = 1 AND U.PRIV_ALTER = 1 THEN 'ALTER' WHEN V1.C1 = 2 AND U.PRIV_CREATE = 1 THEN 'CREATE' WHEN V1.C1 = 3 AND U.PRIV_CREATE_USER = 1 THEN 'CREATE USER' WHEN V1.C1 = 4 AND U.PRIV_DELETE = 1 THEN 'DELETE' WHEN V1.C1 = 5 AND U.PRIV_DROP = 1 THEN 'DROP' WHEN V1.C1 = 7 AND U.PRIV_INSERT = 1 THEN 'INSERT' WHEN V1.C1 = 8 AND U.PRIV_UPDATE = 1 THEN 'UPDATE' WHEN V1.C1 = 9 AND U.PRIV_SELECT = 1 THEN 'SELECT' WHEN V1.C1 = 10 AND U.PRIV_INDEX = 1 THEN 'INDEX' WHEN V1.C1 = 11 AND U.PRIV_CREATE_VIEW = 1 THEN 'CREATE VIEW' WHEN V1.C1 = 12 AND U.PRIV_SHOW_VIEW = 1 THEN 'SHOW VIEW' WHEN V1.C1 = 13 AND U.PRIV_SHOW_DB = 1 THEN 'SHOW DB' WHEN V1.C1 = 14 AND U.PRIV_SUPER = 1 THEN 'SUPER' WHEN V1.C1 = 15 AND U.PRIV_PROCESS = 1 THEN 'PROCESS' WHEN V1.C1 = 17 AND U.PRIV_CREATE_SYNONYM = 1 THEN 'CREATE SYNONYM' WHEN V1.C1 = 27 AND U.PRIV_FILE = 1 THEN 'FILE' WHEN V1.C1 = 28 AND U.PRIV_ALTER_TENANT = 1 THEN 'ALTER TENANT' WHEN V1.C1 = 29 AND U.PRIV_ALTER_SYSTEM = 1 THEN 'ALTER SYSTEM' WHEN V1.C1 = 30 AND U.PRIV_CREATE_RESOURCE_POOL = 1 THEN 'CREATE RESOURCE POOL' WHEN V1.C1 = 31 AND U.PRIV_CREATE_RESOURCE_UNIT = 1 THEN 'CREATE RESOURCE UNIT' WHEN V1.C1 = 33 AND U.PRIV_REPL_SLAVE = 1 THEN 'REPLICATION SLAVE' WHEN V1.C1 = 34 AND U.PRIV_REPL_CLIENT = 1 THEN 'REPLICATION CLIENT' WHEN V1.C1 = 0 AND U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 AND U.PRIV_CREATE_USER = 0 AND U.PRIV_DELETE = 0 AND U.PRIV_DROP = 0 AND U.PRIV_INSERT = 0 AND U.PRIV_UPDATE = 0 AND U.PRIV_SELECT = 0 AND U.PRIV_INDEX = 0 AND U.PRIV_CREATE_VIEW = 0 AND U.PRIV_SHOW_VIEW = 0 AND U.PRIV_SHOW_DB = 0 AND U.PRIV_SUPER = 0 AND U.PRIV_PROCESS = 0 AND U.PRIV_CREATE_SYNONYM = 0 AND U.PRIV_FILE = 0 AND U.PRIV_ALTER_TENANT = 0 AND U.PRIV_ALTER_SYSTEM = 0 AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 AND U.PRIV_REPL_CLIENT = 0 THEN 'USAGE' END PRIVILEGE_TYPE , CASE WHEN U.PRIV_GRANT_OPTION = 0 THEN 'NO' WHEN U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 AND U.PRIV_CREATE_USER = 0 AND U.PRIV_DELETE = 0 AND U.PRIV_DROP = 0 AND U.PRIV_INSERT = 0 AND U.PRIV_UPDATE = 0 AND U.PRIV_SELECT = 0 AND U.PRIV_INDEX = 0 AND U.PRIV_CREATE_VIEW = 0 AND U.PRIV_SHOW_VIEW = 0 AND U.PRIV_SHOW_DB = 0 AND U.PRIV_SUPER = 0 AND U.PRIV_PROCESS = 0 AND U.PRIV_CREATE_SYNONYM = 0 AND U.PRIV_FILE = 0 AND U.PRIV_ALTER_TENANT = 0 AND U.PRIV_ALTER_SYSTEM = 0 AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 AND U.PRIV_REPL_CLIENT = 0 THEN 'NO' WHEN U.PRIV_GRANT_OPTION = 1 THEN 'YES' END IS_GRANTABLE FROM oceanbase.__all_user U, (SELECT 0 AS C1 UNION ALL SELECT 1 AS C1 UNION ALL SELECT 2 AS C1 UNION ALL SELECT 3 AS C1 UNION ALL SELECT 4 AS C1 UNION ALL SELECT 5 AS C1 UNION ALL SELECT 7 AS C1 UNION ALL SELECT 8 AS C1 UNION ALL SELECT 9 AS C1 UNION ALL SELECT 10 AS C1 UNION ALL SELECT 11 AS C1 UNION ALL SELECT 12 AS C1 UNION ALL SELECT 13 AS C1 UNION ALL SELECT 14 AS C1 UNION ALL SELECT 15 AS C1 UNION ALL SELECT 17 AS C1 UNION ALL SELECT 27 AS C1 UNION ALL SELECT 28 AS C1 UNION ALL SELECT 29 AS C1 UNION ALL SELECT 30 AS C1 UNION ALL SELECT 31 AS C1 UNION ALL SELECT 33 AS C1 UNION ALL SELECT 34 AS C1) V1, (SELECT USER_ID FROM oceanbase.__all_user WHERE TENANT_ID = 0 AND CONCAT(USER_NAME, '@', HOST) = CURRENT_USER()) CURR LEFT JOIN (SELECT USER_ID FROM oceanbase.__all_database_privilege WHERE TENANT_ID = 0 AND DATABASE_NAME = 'mysql' AND PRIV_SELECT = 1) DB ON CURR.USER_ID = DB.USER_ID WHERE U.TENANT_ID = 0 AND (DB.USER_ID IS NOT NULL OR 512 & CURRENT_USER_PRIV() = 512 OR U.USER_ID = CURR.USER_ID)) V WHERE V.PRIVILEGE_TYPE IS NOT NULL )__"))) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT CAST(CONCAT('''', V.USER_NAME, '''', '@', '''', V.HOST, '''') AS CHAR(81)) AS GRANTEE , CAST('def' AS CHAR(512)) AS TABLE_CATALOG , CAST(V.PRIVILEGE_TYPE AS CHAR(64)) AS PRIVILEGE_TYPE , CAST(V.IS_GRANTABLE AS CHAR(3)) AS IS_GRANTABLE FROM (SELECT U.USER_NAME AS USER_NAME, U.HOST AS HOST, CASE WHEN V1.C1 = 1 AND U.PRIV_ALTER = 1 THEN 'ALTER' WHEN V1.C1 = 2 AND U.PRIV_CREATE = 1 THEN 'CREATE' WHEN V1.C1 = 3 AND U.PRIV_CREATE_USER = 1 THEN 'CREATE USER' WHEN V1.C1 = 4 AND U.PRIV_DELETE = 1 THEN 'DELETE' WHEN V1.C1 = 5 AND U.PRIV_DROP = 1 THEN 'DROP' WHEN V1.C1 = 7 AND U.PRIV_INSERT = 1 THEN 'INSERT' WHEN V1.C1 = 8 AND U.PRIV_UPDATE = 1 THEN 'UPDATE' WHEN V1.C1 = 9 AND U.PRIV_SELECT = 1 THEN 'SELECT' WHEN V1.C1 = 10 AND U.PRIV_INDEX = 1 THEN 'INDEX' WHEN V1.C1 = 11 AND U.PRIV_CREATE_VIEW = 1 THEN 'CREATE VIEW' WHEN V1.C1 = 12 AND U.PRIV_SHOW_VIEW = 1 THEN 'SHOW VIEW' WHEN V1.C1 = 13 AND U.PRIV_SHOW_DB = 1 THEN 'SHOW DB' WHEN V1.C1 = 14 AND U.PRIV_SUPER = 1 THEN 'SUPER' WHEN V1.C1 = 15 AND U.PRIV_PROCESS = 1 THEN 'PROCESS' WHEN V1.C1 = 17 AND U.PRIV_CREATE_SYNONYM = 1 THEN 'CREATE SYNONYM' WHEN V1.C1 = 27 AND U.PRIV_FILE = 1 THEN 'FILE' WHEN V1.C1 = 28 AND U.PRIV_ALTER_TENANT = 1 THEN 'ALTER TENANT' WHEN V1.C1 = 29 AND U.PRIV_ALTER_SYSTEM = 1 THEN 'ALTER SYSTEM' WHEN V1.C1 = 30 AND U.PRIV_CREATE_RESOURCE_POOL = 1 THEN 'CREATE RESOURCE POOL' WHEN V1.C1 = 31 AND U.PRIV_CREATE_RESOURCE_UNIT = 1 THEN 'CREATE RESOURCE UNIT' WHEN V1.C1 = 33 AND U.PRIV_REPL_SLAVE = 1 THEN 'REPLICATION SLAVE' WHEN V1.C1 = 34 AND U.PRIV_REPL_CLIENT = 1 THEN 'REPLICATION CLIENT' WHEN V1.C1 = 35 AND U.PRIV_DROP_DATABASE_LINK = 1 THEN 'DROP DATABASE LINK' WHEN V1.C1 = 36 AND U.PRIV_CREATE_DATABASE_LINK = 1 THEN 'CREATE DATABASE LINK' WHEN V1.C1 = 0 AND U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 AND U.PRIV_CREATE_USER = 0 AND U.PRIV_DELETE = 0 AND U.PRIV_DROP = 0 AND U.PRIV_INSERT = 0 AND U.PRIV_UPDATE = 0 AND U.PRIV_SELECT = 0 AND U.PRIV_INDEX = 0 AND U.PRIV_CREATE_VIEW = 0 AND U.PRIV_SHOW_VIEW = 0 AND U.PRIV_SHOW_DB = 0 AND U.PRIV_SUPER = 0 AND U.PRIV_PROCESS = 0 AND U.PRIV_CREATE_SYNONYM = 0 AND U.PRIV_FILE = 0 AND U.PRIV_ALTER_TENANT = 0 AND U.PRIV_ALTER_SYSTEM = 0 AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 AND U.PRIV_REPL_CLIENT = 0 AND U.PRIV_DROP_DATABASE_LINK = 0 AND U.PRIV_CREATE_DATABASE_LINK = 0 THEN 'USAGE' END PRIVILEGE_TYPE , CASE WHEN U.PRIV_GRANT_OPTION = 0 THEN 'NO' WHEN U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 AND U.PRIV_CREATE_USER = 0 AND U.PRIV_DELETE = 0 AND U.PRIV_DROP = 0 AND U.PRIV_INSERT = 0 AND U.PRIV_UPDATE = 0 AND U.PRIV_SELECT = 0 AND U.PRIV_INDEX = 0 AND U.PRIV_CREATE_VIEW = 0 AND U.PRIV_SHOW_VIEW = 0 AND U.PRIV_SHOW_DB = 0 AND U.PRIV_SUPER = 0 AND U.PRIV_PROCESS = 0 AND U.PRIV_CREATE_SYNONYM = 0 AND U.PRIV_FILE = 0 AND U.PRIV_ALTER_TENANT = 0 AND U.PRIV_ALTER_SYSTEM = 0 AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 AND U.PRIV_REPL_CLIENT = 0 AND U.PRIV_DROP_DATABASE_LINK = 0 AND U.PRIV_CREATE_DATABASE_LINK = 0 THEN 'NO' WHEN U.PRIV_GRANT_OPTION = 1 THEN 'YES' END IS_GRANTABLE FROM oceanbase.__all_user U, (SELECT 0 AS C1 UNION ALL SELECT 1 AS C1 UNION ALL SELECT 2 AS C1 UNION ALL SELECT 3 AS C1 UNION ALL SELECT 4 AS C1 UNION ALL SELECT 5 AS C1 UNION ALL SELECT 7 AS C1 UNION ALL SELECT 8 AS C1 UNION ALL SELECT 9 AS C1 UNION ALL SELECT 10 AS C1 UNION ALL SELECT 11 AS C1 UNION ALL SELECT 12 AS C1 UNION ALL SELECT 13 AS C1 UNION ALL SELECT 14 AS C1 UNION ALL SELECT 15 AS C1 UNION ALL SELECT 17 AS C1 UNION ALL SELECT 27 AS C1 UNION ALL SELECT 28 AS C1 UNION ALL SELECT 29 AS C1 UNION ALL SELECT 30 AS C1 UNION ALL SELECT 31 AS C1 UNION ALL SELECT 33 AS C1 UNION ALL SELECT 34 AS C1 UNION ALL SELECT 35 AS C1 UNION ALL SELECT 36 AS C1) V1, (SELECT USER_ID FROM oceanbase.__all_user WHERE TENANT_ID = 0 AND CONCAT(USER_NAME, '@', HOST) = CURRENT_USER()) CURR LEFT JOIN (SELECT USER_ID FROM oceanbase.__all_database_privilege WHERE TENANT_ID = 0 AND DATABASE_NAME = 'mysql' AND PRIV_SELECT = 1) DB ON CURR.USER_ID = DB.USER_ID WHERE U.TENANT_ID = 0 AND (DB.USER_ID IS NOT NULL OR 512 & CURRENT_USER_PRIV() = 512 OR U.USER_ID = CURR.USER_ID)) V WHERE V.PRIVILEGE_TYPE IS NOT NULL )__"))) { LOG_ERROR("fail to set view_definition", K(ret)); } } diff --git a/src/share/inner_table/ob_inner_table_schema.21401_21450.cpp b/src/share/inner_table/ob_inner_table_schema.21401_21450.cpp index 47d9510ad4..7701251a42 100644 --- a/src/share/inner_table/ob_inner_table_schema.21401_21450.cpp +++ b/src/share/inner_table/ob_inner_table_schema.21401_21450.cpp @@ -625,6 +625,56 @@ int ObInnerTableSchema::cdb_ob_external_table_files_schema(ObTableSchema &table_ return ret; } +int ObInnerTableSchema::dba_db_links_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_INVALID_ID); + table_schema.set_database_id(OB_SYS_DATABASE_ID); + table_schema.set_table_id(OB_DBA_DB_LINKS_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(0); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(SYSTEM_VIEW); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_DBA_DB_LINKS_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT convert(B.USER_NAME, char(128)) AS OWNER, convert(A.DBLINK_NAME, char(128)) AS DB_LINK, convert(A.USER_NAME, char(128)) AS USERNAME, convert('', char(128)) AS CREDENTIAL_NAME, convert('', char(128)) AS CREDENTIAL_OWNER, convert(CONCAT_WS(':', A.HOST_IP,convert(A.HOST_PORT, char)), char(2000)) AS HOST, convert(A.GMT_CREATE, datetime) AS CREATED, convert('', char(3)) AS HIDDEN, convert('', char(3)) AS SHARD_INTERNAL, convert('YES', char(3)) AS VALID, convert('', char(3)) AS INTRA_CDB, convert(A.TENANT_NAME, char(128)) AS TENANT_NAME, convert(A.DATABASE_NAME, char(128)) AS DATABASE_NAME, convert(A.REVERSE_TENANT_NAME, char(128)) AS REVERSE_TENANT_NAME, convert(A.CLUSTER_NAME, char(128)) AS CLUSTER_NAME, convert(A.REVERSE_CLUSTER_NAME, char(128)) AS REVERSE_CLUSTER_NAME, convert(A.REVERSE_HOST_IP, char(2000)) AS REVERSE_HOST, A.REVERSE_HOST_PORT AS REVERSE_PORT FROM OCEANBASE.__ALL_DBLINK A, OCEANBASE.__ALL_USER B WHERE A.OWNER_ID = B.USER_ID )__"))) { + LOG_ERROR("fail to set view_definition", K(ret)); + } + } + 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); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(0); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + } // end namespace share } // end namespace oceanbase diff --git a/src/share/inner_table/ob_inner_table_schema.h b/src/share/inner_table/ob_inner_table_schema.h index bef504c3d9..73070aa030 100644 --- a/src/share/inner_table/ob_inner_table_schema.h +++ b/src/share/inner_table/ob_inner_table_schema.h @@ -1422,6 +1422,7 @@ public: static int v_sql_join_filter_schema(share::schema::ObTableSchema &table_schema); static int dba_ob_table_stat_stale_info_schema(share::schema::ObTableSchema &table_schema); static int cdb_ob_external_table_files_schema(share::schema::ObTableSchema &table_schema); + static int dba_db_links_schema(share::schema::ObTableSchema &table_schema); static int dba_synonyms_schema(share::schema::ObTableSchema &table_schema); static int dba_objects_ora_schema(share::schema::ObTableSchema &table_schema); static int all_objects_schema(share::schema::ObTableSchema &table_schema); @@ -3716,6 +3717,7 @@ const schema_create_func sys_view_schema_creators [] = { ObInnerTableSchema::v_sql_join_filter_schema, ObInnerTableSchema::dba_ob_table_stat_stale_info_schema, ObInnerTableSchema::cdb_ob_external_table_files_schema, + ObInnerTableSchema::dba_db_links_schema, ObInnerTableSchema::dba_synonyms_schema, ObInnerTableSchema::dba_objects_ora_schema, ObInnerTableSchema::all_objects_schema, @@ -5072,6 +5074,7 @@ const uint64_t tenant_space_tables [] = { OB_GV_SQL_JOIN_FILTER_TID, OB_V_SQL_JOIN_FILTER_TID, OB_DBA_OB_TABLE_STAT_STALE_INFO_TID, + OB_DBA_DB_LINKS_TID, OB_DBA_SYNONYMS_TID, OB_DBA_OBJECTS_ORA_TID, OB_ALL_OBJECTS_TID, @@ -7166,6 +7169,7 @@ const char* const tenant_space_table_names [] = { OB_GV_SQL_JOIN_FILTER_TNAME, OB_V_SQL_JOIN_FILTER_TNAME, OB_DBA_OB_TABLE_STAT_STALE_INFO_TNAME, + OB_DBA_DB_LINKS_TNAME, OB_DBA_SYNONYMS_TNAME, OB_DBA_OBJECTS_ORA_TNAME, OB_ALL_OBJECTS_TNAME, @@ -10519,10 +10523,10 @@ static inline int get_sys_table_lob_aux_schema(const uint64_t tid, const int64_t OB_CORE_TABLE_COUNT = 4; const int64_t OB_SYS_TABLE_COUNT = 233; const int64_t OB_VIRTUAL_TABLE_COUNT = 671; -const int64_t OB_SYS_VIEW_COUNT = 713; -const int64_t OB_SYS_TENANT_TABLE_COUNT = 1622; +const int64_t OB_SYS_VIEW_COUNT = 714; +const int64_t OB_SYS_TENANT_TABLE_COUNT = 1623; const int64_t OB_CORE_SCHEMA_VERSION = 1; -const int64_t OB_BOOTSTRAP_SCHEMA_VERSION = 1625; +const int64_t OB_BOOTSTRAP_SCHEMA_VERSION = 1626; } // end namespace share } // end namespace oceanbase diff --git a/src/share/inner_table/ob_inner_table_schema_constants.h b/src/share/inner_table/ob_inner_table_schema_constants.h index fb84dfdc90..9d496228a9 100644 --- a/src/share/inner_table/ob_inner_table_schema_constants.h +++ b/src/share/inner_table/ob_inner_table_schema_constants.h @@ -1164,6 +1164,7 @@ const uint64_t OB_GV_SQL_JOIN_FILTER_TID = 21421; // "GV$SQL_JOIN_FILTER" const uint64_t OB_V_SQL_JOIN_FILTER_TID = 21422; // "V$SQL_JOIN_FILTER" const uint64_t OB_DBA_OB_TABLE_STAT_STALE_INFO_TID = 21423; // "DBA_OB_TABLE_STAT_STALE_INFO" const uint64_t OB_CDB_OB_EXTERNAL_TABLE_FILES_TID = 21425; // "CDB_OB_EXTERNAL_TABLE_FILES" +const uint64_t OB_DBA_DB_LINKS_TID = 21426; // "DBA_DB_LINKS" const uint64_t OB_DBA_SYNONYMS_TID = 25001; // "DBA_SYNONYMS" const uint64_t OB_DBA_OBJECTS_ORA_TID = 25002; // "DBA_OBJECTS_ORA" const uint64_t OB_ALL_OBJECTS_TID = 25003; // "ALL_OBJECTS" @@ -3352,6 +3353,7 @@ const char *const OB_GV_SQL_JOIN_FILTER_TNAME = "GV$SQL_JOIN_FILTER"; const char *const OB_V_SQL_JOIN_FILTER_TNAME = "V$SQL_JOIN_FILTER"; const char *const OB_DBA_OB_TABLE_STAT_STALE_INFO_TNAME = "DBA_OB_TABLE_STAT_STALE_INFO"; const char *const OB_CDB_OB_EXTERNAL_TABLE_FILES_TNAME = "CDB_OB_EXTERNAL_TABLE_FILES"; +const char *const OB_DBA_DB_LINKS_TNAME = "DBA_DB_LINKS"; const char *const OB_DBA_SYNONYMS_TNAME = "DBA_SYNONYMS"; const char *const OB_DBA_OBJECTS_ORA_TNAME = "DBA_OBJECTS"; const char *const OB_ALL_OBJECTS_TNAME = "ALL_OBJECTS"; diff --git a/src/share/inner_table/ob_inner_table_schema_def.py b/src/share/inner_table/ob_inner_table_schema_def.py index 3bf608acc6..5ca8318951 100644 --- a/src/share/inner_table/ob_inner_table_schema_def.py +++ b/src/share/inner_table/ob_inner_table_schema_def.py @@ -408,6 +408,8 @@ all_user_def = dict( ('max_user_connections', 'int', 'false', '0'), ('priv_repl_slave', 'int', 'false', '0'), ('priv_repl_client', 'int', 'false', '0'), + ('priv_drop_database_link', 'int', 'false', '0'), + ('priv_create_database_link', 'int', 'false', '0'), ], ) @@ -1951,7 +1953,7 @@ all_dblink_def = dict( normal_columns = [ ('dblink_name', 'varchar:OB_MAX_DBLINK_NAME_LENGTH', 'false'), ('owner_id', 'int', 'false'), - ('host_ip', 'varchar:MAX_IP_ADDR_LENGTH', 'false'), + ('host_ip', 'varchar:OB_MAX_DOMIN_NAME_LENGTH', 'false'), ('host_port', 'int', 'false'), ('cluster_name', 'varchar:OB_MAX_CLUSTER_NAME_LENGTH', 'true'), ('tenant_name', 'varchar:OB_MAX_TENANT_NAME_LENGTH_STORE', 'false'), @@ -1972,6 +1974,7 @@ all_dblink_def = dict( ('reverse_tenant_name', 'varchar:OB_MAX_TENANT_NAME_LENGTH_STORE', 'true'), ('reverse_user_name', 'varchar:OB_MAX_USER_NAME_LENGTH_STORE', 'true'), ('reverse_password', 'varchar:OB_MAX_ENCRYPTED_PASSWORD_LENGTH', 'true'), + ('database_name', 'varchar:OB_MAX_DATABASE_NAME_LENGTH', 'true'), ], ) @@ -8315,6 +8318,8 @@ def_table_schema( ('authentication_string', 'varchar:1024'), ('password_expired', 'varchar:1'), ('account_locked', 'varchar:1'), + ('drop_database_link_priv', 'varchar:1'), + ('create_database_link_priv', 'varchar:1'), ], ) @@ -24693,7 +24698,9 @@ def_table_schema( MAX_CONNECTIONS, MAX_USER_CONNECTIONS, (CASE WHEN PRIV_REPL_SLAVE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_SLAVE, - (CASE WHEN PRIV_REPL_CLIENT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_CLIENT + (CASE WHEN PRIV_REPL_CLIENT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_CLIENT, + (CASE WHEN PRIV_DROP_DATABASE_LINK = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_DROP_DATABASE_LINK, + (CASE WHEN PRIV_CREATE_DATABASE_LINK = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_DATABASE_LINK FROM OCEANBASE.__all_user; """.replace("\n", " ") ) @@ -24745,7 +24752,9 @@ def_table_schema( MAX_CONNECTIONS, MAX_USER_CONNECTIONS, (CASE WHEN PRIV_REPL_SLAVE = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_SLAVE, - (CASE WHEN PRIV_REPL_CLIENT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_CLIENT + (CASE WHEN PRIV_REPL_CLIENT = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_REPL_CLIENT, + (CASE WHEN PRIV_DROP_DATABASE_LINK = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_DROP_DATABASE_LINK, + (CASE WHEN PRIV_CREATE_DATABASE_LINK = 0 THEN 'NO' ELSE 'YES' END) AS PRIV_CREATE_DATABASE_LINK FROM OCEANBASE.__all_virtual_user; """.replace("\n", " ") ) @@ -25232,6 +25241,10 @@ def_table_schema( AND U.PRIV_REPL_SLAVE = 1 THEN 'REPLICATION SLAVE' WHEN V1.C1 = 34 AND U.PRIV_REPL_CLIENT = 1 THEN 'REPLICATION CLIENT' + WHEN V1.C1 = 35 + AND U.PRIV_DROP_DATABASE_LINK = 1 THEN 'DROP DATABASE LINK' + WHEN V1.C1 = 36 + AND U.PRIV_CREATE_DATABASE_LINK = 1 THEN 'CREATE DATABASE LINK' WHEN V1.C1 = 0 AND U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 @@ -25254,7 +25267,9 @@ def_table_schema( AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 - AND U.PRIV_REPL_CLIENT = 0 THEN 'USAGE' + AND U.PRIV_REPL_CLIENT = 0 + AND U.PRIV_DROP_DATABASE_LINK = 0 + AND U.PRIV_CREATE_DATABASE_LINK = 0 THEN 'USAGE' END PRIVILEGE_TYPE , CASE WHEN U.PRIV_GRANT_OPTION = 0 THEN 'NO' @@ -25279,7 +25294,9 @@ def_table_schema( AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 - AND U.PRIV_REPL_CLIENT = 0 THEN 'NO' + AND U.PRIV_REPL_CLIENT = 0 + AND U.PRIV_DROP_DATABASE_LINK = 0 + AND U.PRIV_CREATE_DATABASE_LINK = 0 THEN 'NO' WHEN U.PRIV_GRANT_OPTION = 1 THEN 'YES' END IS_GRANTABLE FROM oceanbase.__all_user U, @@ -25305,7 +25322,9 @@ def_table_schema( UNION ALL SELECT 30 AS C1 UNION ALL SELECT 31 AS C1 UNION ALL SELECT 33 AS C1 - UNION ALL SELECT 34 AS C1) V1, + UNION ALL SELECT 34 AS C1 + UNION ALL SELECT 35 AS C1 + UNION ALL SELECT 36 AS C1) V1, (SELECT USER_ID FROM oceanbase.__all_user WHERE TENANT_ID = 0 @@ -26971,7 +26990,6 @@ JOIN OCEANBASE.__ALL_OPTSTAT_GLOBAL_PREFS GP ) # 21424: V$OB_LS_LOG_RESTORE_STATUS - def_table_schema( owner = 'jim.wjh', table_name = 'CDB_OB_EXTERNAL_TABLE_FILES', @@ -26996,6 +27014,42 @@ def_table_schema( """.replace("\n", " ") ) +def_table_schema( + owner = 'ailing.lcq', + table_name = 'DBA_DB_LINKS', + table_id = '21426', + table_type = 'SYSTEM_VIEW', + gm_columns = [], + in_tenant_space = True, + rowkey_columns = [], + view_definition = """ + SELECT + convert(B.USER_NAME, char(128)) AS OWNER, + convert(A.DBLINK_NAME, char(128)) AS DB_LINK, + convert(A.USER_NAME, char(128)) AS USERNAME, + convert('', char(128)) AS CREDENTIAL_NAME, + convert('', char(128)) AS CREDENTIAL_OWNER, + convert(CONCAT_WS(':', A.HOST_IP,convert(A.HOST_PORT, char)), char(2000)) AS HOST, + convert(A.GMT_CREATE, datetime) AS CREATED, + convert('', char(3)) AS HIDDEN, + convert('', char(3)) AS SHARD_INTERNAL, + convert('YES', char(3)) AS VALID, + convert('', char(3)) AS INTRA_CDB, + convert(A.TENANT_NAME, char(128)) AS TENANT_NAME, + convert(A.DATABASE_NAME, char(128)) AS DATABASE_NAME, + convert(A.REVERSE_TENANT_NAME, char(128)) AS REVERSE_TENANT_NAME, + convert(A.CLUSTER_NAME, char(128)) AS CLUSTER_NAME, + convert(A.REVERSE_CLUSTER_NAME, char(128)) AS REVERSE_CLUSTER_NAME, + convert(A.REVERSE_HOST_IP, char(2000)) AS REVERSE_HOST, + A.REVERSE_HOST_PORT AS REVERSE_PORT + FROM OCEANBASE.__ALL_DBLINK A, + OCEANBASE.__ALL_USER B + WHERE A.OWNER_ID = B.USER_ID +""".replace("\n", " "), + normal_columns = [ + ], +) + ################################################################################ # Oracle System View (25000, 30000] # Data Dictionary View (25000, 28000] diff --git a/src/share/ob_errno.cpp b/src/share/ob_errno.cpp index afc61e269a..cc18c26aad 100644 --- a/src/share/ob_errno.cpp +++ b/src/share/ob_errno.cpp @@ -17236,10 +17236,10 @@ static const _error _error_OB_ERR_DBLINK_REMOTE_ECODE = { .mysql_errno = -1, .sqlstate = "HY000", .str_error = "Unknown errorcode: %d", - .str_user_error = "dblink remote ora error code: %d", + .str_user_error = "Unknown errorcode: %d", .oracle_errno = 600, .oracle_str_error = "ORA-00600: internal error code, arguments: -5975, Unknown errorcode: %d", - .oracle_str_user_error = "ORA-00600: internal error code, arguments: -5975, dblink remote ora error code: %d" + .oracle_str_user_error = "ORA-00600: internal error code, arguments: -5975, Unknown errorcode: %d" }; static const _error _error_OB_ERR_DBLINK_NO_LIB = { .error_name = "OB_ERR_DBLINK_NO_LIB", @@ -26987,6 +26987,26 @@ inline const _error *get_error(int index) return _errors[index]; } +int get_oracle_errno(int index) +{ + return get_error(index)->oracle_errno; +} + +int get_mysql_errno(int index) +{ + return get_error(index)->mysql_errno; +} + +const char* get_oracle_str_error(int index) +{ + return get_error(index)->oracle_str_error; +} + +const char* get_mysql_str_error(int index) +{ + return get_error(index)->str_error; +} + namespace oceanbase { namespace common @@ -27107,57 +27127,6 @@ int g_all_ob_errnos[2072] = {0, -4000, -4001, -4002, -4003, -4004, -4005, -4006, } return ret; } -#ifndef __ERROR_CODE_PARSER_ - int get_ob_errno_from_oracle_errno(const int error_no, const char *error_msg, int &ob_errno) { - const int orcl_errno = abs(error_no); - ob_errno = error_no; - int64_t edit_dist = 0x7fffffffffffffff; - int64_t min_edit_dist = 0x7fffffffffffffff; - if (-4016 == error_no || // error_no mayby oceanbase inner errro number sometimes, need skip it - -4013 == error_no || - -4012 == error_no || - -4007 == error_no || - -4002 == error_no) { - } else if (-2013 == error_no || // error_no mayby mysql inner errro number sometimes - -2006 == error_no) { - ob_errno = OB_ERR_UNEXPECTED; - LOG_USER_ERROR(OB_ERR_UNEXPECTED, "local server's dblink can not connect to remote sever by mysqlclient(interal error code: 2006 or 2013)"); - } else if (nullptr == error_msg) { // error_no maybe oracle inner error number at most times. - for (int i = 0; i < OB_MAX_ERROR_CODE; ++i) { - if (orcl_errno == get_error(i)->oracle_errno) { - ob_errno = -i; - break; - } - } - } else { - ObEditDistance ed; - for (int i = 0; i < OB_MAX_ERROR_CODE; ++i) { - if (orcl_errno == get_error(i)->oracle_errno) { - const char *orcl_str_error = get_error(i)->oracle_str_user_error; - if (nullptr == orcl_str_error) { - // In the case of a null pointer boundary, - // the reason for setting edit_distance to 0x7ffffffffffffffe is to deal with the situation where - // error_msg does not match ORACLE_STR_USER_ERROR[i] but orcl_errno == ORACLE_ERRNO[i]. - edit_dist = 0x7ffffffffffffffe; - } else { - // The edit distance between the strings is used to measure their similarity. - // The smaller the edit distance, the greater the similarity, so as to find the most similar error message. - ObEditDistance::cal_edit_distance(error_msg, orcl_str_error, STRLEN(error_msg), STRLEN(orcl_str_error), edit_dist); - } - if (edit_dist < min_edit_dist) { - ob_errno = -i; - min_edit_dist = edit_dist; - if (0 == min_edit_dist) { - break; - } - } - } - } - } - LOG_TRACE("trace the ob_errno and oracle_errno.", K(ob_errno), K(error_no), K(min_edit_dist)); - return OB_SUCCESS; - } -#endif int ob_oracle_errno(const int err) { int ret = -1; diff --git a/src/share/ob_errno.def b/src/share/ob_errno.def index 2aa2162651..6ba588015c 100644 --- a/src/share/ob_errno.def +++ b/src/share/ob_errno.def @@ -1571,7 +1571,7 @@ DEFINE_ORACLE_ERROR_EXT(OB_ERR_CHECK_OPTION_VIOLATED, -5971, ER_VIEW_CHECK_FAILE DEFINE_ERROR_EXT(OB_ERR_CHECK_OPTION_ON_NONUPDATABLE_VIEW, -5972, ER_VIEW_NONUPD_CHECK, "HY000", "CHECK OPTION on non-updatable view", "CHECK OPTION on non-updatable view '%.*s.%.*s'"); DEFINE_ORACLE_ERROR(OB_ERR_NO_DESC_FOR_POS, -5973, -1, "HY000", "no descriptor for this position", 24334, "no descriptor for this position"); DEFINE_ORACLE_ERROR(OB_ERR_ILL_OBJ_FLAG, -5974, -1, "HY000", "object specified is incompatible with the flag specified", 4047, "object specified is incompatible with the flag specified"); -DEFINE_ERROR_EXT(OB_ERR_DBLINK_REMOTE_ECODE, -5975, -1, "HY000", "Unknown errorcode: %d", "dblink remote ora error code: %d"); +DEFINE_ERROR_DEP(OB_ERR_DBLINK_REMOTE_ECODE, -5975, -1, "HY000", "Unknown errorcode: %d", "dblink remote ora error code: %d"); DEFINE_ERROR_DEP(OB_ERR_DBLINK_NO_LIB, -5976, -1, "HY000", "oci lib not founded"); DEFINE_ORACLE_ERROR(OB_ERR_PARTITION_EXTENDED_ON_VIEW, -5977, -1, "HY000", "partition-extended object names may only be used with tables and editioning views", 14109, "partition-extended object names may only be used with tables and editioning views"); DEFINE_ORACLE_ERROR(OB_ERR_NOT_ALL_VARIABLE_BIND, -5978, -1, "HY000", "not all variables bound", 1008, "not all variables bound"); diff --git a/src/share/ob_errno.h b/src/share/ob_errno.h index cfb0f970c2..1e103bfb3e 100644 --- a/src/share/ob_errno.h +++ b/src/share/ob_errno.h @@ -1219,7 +1219,6 @@ constexpr int OB_ERR_CHECK_OPTION_VIOLATED = -5971; constexpr int OB_ERR_CHECK_OPTION_ON_NONUPDATABLE_VIEW = -5972; constexpr int OB_ERR_NO_DESC_FOR_POS = -5973; constexpr int OB_ERR_ILL_OBJ_FLAG = -5974; -constexpr int OB_ERR_DBLINK_REMOTE_ECODE = -5975; constexpr int OB_ERR_PARTITION_EXTENDED_ON_VIEW = -5977; constexpr int OB_ERR_NOT_ALL_VARIABLE_BIND = -5978; constexpr int OB_ERR_BIND_VARIABLE_NOT_EXIST = -5979; @@ -3177,7 +3176,7 @@ constexpr int OB_ERR_INVALID_DATE_MSG_FMT_V2 = -4219; #define OB_ERR_CHECK_OPTION_ON_NONUPDATABLE_VIEW__USER_ERROR_MSG "CHECK OPTION on non-updatable view '%.*s.%.*s'" #define OB_ERR_NO_DESC_FOR_POS__USER_ERROR_MSG "no descriptor for this position" #define OB_ERR_ILL_OBJ_FLAG__USER_ERROR_MSG "object specified is incompatible with the flag specified" -#define OB_ERR_DBLINK_REMOTE_ECODE__USER_ERROR_MSG "dblink remote ora error code: %d" +#define OB_ERR_DBLINK_REMOTE_ECODE__USER_ERROR_MSG "Unknown errorcode: %d" #define OB_ERR_DBLINK_NO_LIB__USER_ERROR_MSG "oci lib not founded" #define OB_ERR_PARTITION_EXTENDED_ON_VIEW__USER_ERROR_MSG "partition-extended object names may only be used with tables and editioning views" #define OB_ERR_NOT_ALL_VARIABLE_BIND__USER_ERROR_MSG "not all variables bound" @@ -5253,7 +5252,7 @@ constexpr int OB_ERR_INVALID_DATE_MSG_FMT_V2 = -4219; #define OB_ERR_CHECK_OPTION_ON_NONUPDATABLE_VIEW__ORA_USER_ERROR_MSG "ORA-00600: internal error code, arguments: -5972, CHECK OPTION on non-updatable view '%.*s.%.*s'" #define OB_ERR_NO_DESC_FOR_POS__ORA_USER_ERROR_MSG "ORA-24334: no descriptor for this position" #define OB_ERR_ILL_OBJ_FLAG__ORA_USER_ERROR_MSG "ORA-04047: object specified is incompatible with the flag specified" -#define OB_ERR_DBLINK_REMOTE_ECODE__ORA_USER_ERROR_MSG "ORA-00600: internal error code, arguments: -5975, dblink remote ora error code: %d" +#define OB_ERR_DBLINK_REMOTE_ECODE__ORA_USER_ERROR_MSG "ORA-00600: internal error code, arguments: -5975, Unknown errorcode: %d" #define OB_ERR_DBLINK_NO_LIB__ORA_USER_ERROR_MSG "ORA-00600: internal error code, arguments: -5976, oci lib not founded" #define OB_ERR_PARTITION_EXTENDED_ON_VIEW__ORA_USER_ERROR_MSG "ORA-14109: partition-extended object names may only be used with tables and editioning views" #define OB_ERR_NOT_ALL_VARIABLE_BIND__ORA_USER_ERROR_MSG "ORA-01008: not all variables bound" diff --git a/src/share/ob_rpc_struct.cpp b/src/share/ob_rpc_struct.cpp index e2b90f94b6..2d09016e81 100644 --- a/src/share/ob_rpc_struct.cpp +++ b/src/share/ob_rpc_struct.cpp @@ -4804,7 +4804,7 @@ bool ObDropDbLinkArg::is_valid() const return OB_INVALID_ID != tenant_id_ && !dblink_name_.empty(); } -OB_SERIALIZE_MEMBER((ObDropDbLinkArg, ObDDLArg), tenant_id_, dblink_name_); +OB_SERIALIZE_MEMBER((ObDropDbLinkArg, ObDDLArg), tenant_id_, dblink_name_, if_exist_); OB_SERIALIZE_MEMBER((ObUseDatabaseArg, ObDDLArg)); OB_SERIALIZE_MEMBER(ObGetPartitionCountResult, partition_count_); diff --git a/src/share/ob_rpc_struct.h b/src/share/ob_rpc_struct.h index d53aa204ee..cfc53db703 100644 --- a/src/share/ob_rpc_struct.h +++ b/src/share/ob_rpc_struct.h @@ -5569,12 +5569,13 @@ struct ObDropDbLinkArg : public ObDDLArg { OB_UNIS_VERSION(1); public: - ObDropDbLinkArg() : ObDDLArg(), tenant_id_(common::OB_INVALID_ID), dblink_name_() {} + ObDropDbLinkArg() : ObDDLArg(), tenant_id_(common::OB_INVALID_ID), dblink_name_(), if_exist_(false) {} virtual ~ObDropDbLinkArg() {} bool is_valid() const; - TO_STRING_KV(K_(tenant_id), K_(dblink_name)); + TO_STRING_KV(K_(tenant_id), K_(dblink_name), K_(if_exist)); uint64_t tenant_id_; common::ObString dblink_name_; + bool if_exist_; }; struct ObUseDatabaseArg : public ObDDLArg diff --git a/src/share/ob_upgrade_utils.cpp b/src/share/ob_upgrade_utils.cpp index 99d7461c7f..085ef18c7a 100644 --- a/src/share/ob_upgrade_utils.cpp +++ b/src/share/ob_upgrade_utils.cpp @@ -964,12 +964,100 @@ int ObUpgradeFor4200Processor::post_upgrade() int ret = OB_SUCCESS; if (OB_FAIL(check_inner_stat())) { LOG_WARN("fail to check inner stat", KR(ret)); + } else if (OB_FAIL(post_upgrade_for_grant_create_database_link_priv())) { + LOG_WARN("grant create database link failed", K(ret)); + } else if (OB_FAIL(post_upgrade_for_grant_drop_database_link_priv())) { + LOG_WARN("grant drop database link failed", K(ret)); } else if (OB_FAIL(post_upgrade_for_heartbeat_and_server_zone_op_service())) { LOG_WARN("post upgrade for heartbeat and server zone op service failed", KR(ret)); } return ret; } +int ObUpgradeFor4200Processor::post_upgrade_for_grant_create_database_link_priv() +{ + int ret = OB_SUCCESS; + ObString sql("grant create database link on *.* to root"); + int64_t start = ObTimeUtility::current_time(); + int64_t affected_rows = 0; + ObSchemaGetterGuard schema_guard; + common::ObSEArray user_infos; + ObString root_name("root"); + bool has_priv = true; + if (OB_ISNULL(schema_service_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret)); + } else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id_, schema_guard))) { + LOG_WARN("failed to get schema guard", K(ret)); + } else if (OB_FAIL(schema_guard.get_user_info(tenant_id_, root_name, user_infos))) { + LOG_WARN("get root user failed", K(ret)); + } else { + for (int64_t i = 0; has_priv && OB_SUCC(ret) && i < user_infos.count(); ++i) { + const ObUserInfo *user_info = user_infos.at(i); + if (OB_ISNULL(user_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret)); + } else { + has_priv = has_priv && (OB_PRIV_CREATE_DATABASE_LINK & user_info->get_priv_set()); + } + } + if (OB_FAIL(ret) || has_priv) { + // do nothing + } else if (OB_ISNULL(sql_proxy_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret)); + } else if (OB_FAIL(sql_proxy_->write(tenant_id_, sql.ptr(), affected_rows))) { + LOG_WARN("execute sql failed", K(ret), K(sql)); + } else { + LOG_TRACE("execute sql", KR(ret), K(tenant_id_), K(sql), K(affected_rows)); + } + } + LOG_INFO("set create database link priv", K(ret), K(tenant_id_), K(affected_rows), "cost", ObTimeUtility::current_time() - start); + return ret; +} + +int ObUpgradeFor4200Processor::post_upgrade_for_grant_drop_database_link_priv() +{ + int ret = OB_SUCCESS; + ObString sql("grant drop database link on *.* to root"); + int64_t start = ObTimeUtility::current_time(); + int64_t affected_rows = 0; + ObSchemaGetterGuard schema_guard; + common::ObSEArray user_infos; + ObString root_name("root"); + bool has_priv = true; + if (OB_ISNULL(schema_service_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret)); + } else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id_, schema_guard))) { + LOG_WARN("failed to get schema guard", K(ret)); + } else if (OB_FAIL(schema_guard.get_user_info(tenant_id_, root_name, user_infos))) { + LOG_WARN("get root user failed", K(ret)); + } else { + for (int64_t i = 0; has_priv && OB_SUCC(ret) && i < user_infos.count(); ++i) { + const ObUserInfo *user_info = user_infos.at(i); + if (OB_ISNULL(user_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret)); + } else { + has_priv = has_priv && (OB_PRIV_DROP_DATABASE_LINK & user_info->get_priv_set()); + } + } + if (OB_FAIL(ret) || has_priv) { + // do nothing + } else if (OB_ISNULL(sql_proxy_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret)); + } else if (OB_FAIL(sql_proxy_->write(tenant_id_, sql.ptr(), affected_rows))) { + LOG_WARN("execute sql failed", K(ret), K(sql)); + } else { + LOG_TRACE("execute sql", KR(ret), K(tenant_id_), K(sql), K(affected_rows)); + } + } + LOG_INFO("set drop database link priv", K(ret), K(tenant_id_), K(affected_rows), "cost", ObTimeUtility::current_time() - start); + return ret; +} + int ObUpgradeFor4200Processor::post_upgrade_for_heartbeat_and_server_zone_op_service() { int ret = OB_SUCCESS; diff --git a/src/share/ob_upgrade_utils.h b/src/share/ob_upgrade_utils.h index 62e4b16f91..82cd4edeb3 100644 --- a/src/share/ob_upgrade_utils.h +++ b/src/share/ob_upgrade_utils.h @@ -189,7 +189,7 @@ private: int init_rewrite_rule_version(const uint64_t tenant_id); static int recompile_all_views_and_synonyms(const uint64_t tenant_id); }; -// DEF_SIMPLE_UPGRARD_PROCESSER(4, 2, 0, 0) + class ObUpgradeFor4200Processor : public ObBaseUpgradeProcessor { public: @@ -198,6 +198,8 @@ public: virtual int pre_upgrade() override { return common::OB_SUCCESS; } virtual int post_upgrade() override; private: + int post_upgrade_for_grant_create_database_link_priv(); + int post_upgrade_for_grant_drop_database_link_priv(); int post_upgrade_for_heartbeat_and_server_zone_op_service(); }; /* =========== special upgrade processor end ============= */ diff --git a/src/share/schema/ob_dblink_sql_service.cpp b/src/share/schema/ob_dblink_sql_service.cpp index 43a7a79427..0d18b9e117 100644 --- a/src/share/schema/ob_dblink_sql_service.cpp +++ b/src/share/schema/ob_dblink_sql_service.cpp @@ -123,7 +123,17 @@ int ObDbLinkSqlService::add_normal_columns(const ObDbLinkBaseInfo &dblink_info, ObString reverse_host_ip; char ip_buf[MAX_IP_ADDR_LENGTH] = {0}; char reverse_ip_buf[MAX_IP_ADDR_LENGTH] = {0}; - if (!dblink_info.get_host_addr().ip_to_string(ip_buf, sizeof(ip_buf))) { + uint64_t compat_version = 0; + bool is_oracle_mode = false; + uint64_t tenant_id = dblink_info.get_tenant_id(); + if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { + LOG_WARN("fail to get data version", KR(ret), K(tenant_id)); + } else if (OB_FAIL(ObCompatModeGetter::check_is_oracle_mode_with_tenant_id(tenant_id, is_oracle_mode))) { + LOG_WARN("fail to check is oracle mode", K(ret)); + } else if (compat_version < DATA_VERSION_4_2_0_0 && !is_oracle_mode) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("mysql dblink is not supported when MIN_DATA_VERSION is below DATA_VERSION_4_2_0_0", K(ret)); + } else if (!dblink_info.get_host_addr().ip_to_string(ip_buf, sizeof(ip_buf))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("failed to ip to string", K(ret), K(dblink_info.get_host_addr())); } else if (FALSE_IT(host_ip.assign_ptr(ip_buf, static_cast(STRLEN(ip_buf))))) { @@ -198,6 +208,16 @@ int ObDbLinkSqlService::add_normal_columns(const ObDbLinkBaseInfo &dblink_info, || OB_FAIL(dml.add_column("reverse_password", dblink_info.get_reverse_password()))) { LOG_WARN("failed to add encrypted_password column", K(ret), K(encrypted_password)); } + if (OB_FAIL(ret)) { + // do nothing + } else if (compat_version < DATA_VERSION_4_2_0_0) { + if (!dblink_info.get_database_name().empty()) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("some column of dblink_info is not empty when MIN_DATA_VERSION is below DATA_VERSION_4_2_0_0", K(ret), K(dblink_info.get_database_name())); + } + } else if (OB_FAIL(dml.add_column("database_name", dblink_info.get_database_name()))) { + LOG_WARN("failed to add normal database_name", K(dblink_info.get_database_name()), K(ret)); + } } } diff --git a/src/share/schema/ob_multi_version_schema_service.cpp b/src/share/schema/ob_multi_version_schema_service.cpp index 8705e4f743..24986d822e 100644 --- a/src/share/schema/ob_multi_version_schema_service.cpp +++ b/src/share/schema/ob_multi_version_schema_service.cpp @@ -3959,7 +3959,8 @@ int ObMultiVersionSchemaService::fetch_link_table_schema(const ObDbLinkSchema *d ObTableSchema *&table_schema, sql::ObSQLSessionInfo *session_info, const ObString &dblink_name, - bool is_reverse_link) + bool is_reverse_link, + uint64_t *current_scn) { int ret = OB_SUCCESS; if (OB_ISNULL(schema_service_)) { @@ -3970,7 +3971,8 @@ int ObMultiVersionSchemaService::fetch_link_table_schema(const ObDbLinkSchema *d allocator, table_schema, session_info, dblink_name, - is_reverse_link))) { + is_reverse_link, + current_scn))) { LOG_WARN("get link table schema failed", K(ret), K(is_reverse_link)); } return ret; diff --git a/src/share/schema/ob_multi_version_schema_service.h b/src/share/schema/ob_multi_version_schema_service.h index 6b0f724b06..1f634c043c 100644 --- a/src/share/schema/ob_multi_version_schema_service.h +++ b/src/share/schema/ob_multi_version_schema_service.h @@ -202,7 +202,8 @@ public: ObTableSchema *&table_schema, sql::ObSQLSessionInfo *session_info, const ObString &dblink_name, - bool is_reverse_link); + bool is_reverse_link, + uint64_t *current_scn); // get the latest schema version // if core_schema_version = false, return user schema version diff --git a/src/share/schema/ob_priv_mgr.cpp b/src/share/schema/ob_priv_mgr.cpp index c8fb712748..4fdb497829 100644 --- a/src/share/schema/ob_priv_mgr.cpp +++ b/src/share/schema/ob_priv_mgr.cpp @@ -71,6 +71,8 @@ const char *ObPrivMgr::priv_names_[] = { "DEBUG", "REPLICATION SLAVE", "REPLICATION CLIENT", + "DROP DATABASE LINK", + "CREATE DATABASE LINK", }; ObPrivMgr::ObPrivMgr() diff --git a/src/share/schema/ob_priv_sql_service.cpp b/src/share/schema/ob_priv_sql_service.cpp index 6d062097eb..2d89efb2b3 100644 --- a/src/share/schema/ob_priv_sql_service.cpp +++ b/src/share/schema/ob_priv_sql_service.cpp @@ -813,7 +813,8 @@ int ObPrivSqlService::alter_user_default_role( if (OB_FAIL((schema_service_.get_user_sql_service()).grant_revoke_user(user_info, new_schema_version, ddl_stmt_str, - sql_client))) { + sql_client, + false))) { LOG_WARN("fail to push back", K(ret), K(user_info)); } } @@ -946,7 +947,8 @@ int ObPrivSqlService::grant_revoke_role( if (OB_FAIL((schema_service_.get_user_sql_service()).grant_revoke_user(user_info, new_schema_version, ddl_stmt_str, - sql_client))) { + sql_client, + false))) { LOG_WARN("fail to push back", K(ret), K(user_info)); } } diff --git a/src/share/schema/ob_priv_type.h b/src/share/schema/ob_priv_type.h index 3854d5e91c..5e50e814cf 100644 --- a/src/share/schema/ob_priv_type.h +++ b/src/share/schema/ob_priv_type.h @@ -63,6 +63,8 @@ enum OB_PRIV_SHIFT OB_PRIV_DEBUG_SHIFT, OB_PRIV_REPL_SLAVE_SHIFT, OB_PRIV_REPL_CLIENT_SHIFT, + OB_PRIV_DROP_DATABASE_LINK_SHIFT, + OB_PRIV_CREATE_DATABASE_LINK_SHIFT, OB_PRIV_MAX_SHIFT_PLUS_ONE }; @@ -104,7 +106,8 @@ enum OB_PRIV_SHIFT #define OB_PRIV_DEBUG OB_PRIV_GET_TYPE(OB_PRIV_DEBUG_SHIFT) #define OB_PRIV_REPL_SLAVE OB_PRIV_GET_TYPE(OB_PRIV_REPL_SLAVE_SHIFT) #define OB_PRIV_REPL_CLIENT OB_PRIV_GET_TYPE(OB_PRIV_REPL_CLIENT_SHIFT) - +#define OB_PRIV_DROP_DATABASE_LINK OB_PRIV_GET_TYPE(OB_PRIV_DROP_DATABASE_LINK_SHIFT) +#define OB_PRIV_CREATE_DATABASE_LINK OB_PRIV_GET_TYPE(OB_PRIV_CREATE_DATABASE_LINK_SHIFT) #define OB_PRIV_ALL \ (OB_PRIV_ALTER | OB_PRIV_CREATE | OB_PRIV_CREATE_USER | OB_PRIV_DELETE | \ @@ -113,7 +116,8 @@ enum OB_PRIV_SHIFT OB_PRIV_SUPER | OB_PRIV_PROCESS | OB_PRIV_CREATE_SYNONYM | OB_PRIV_FILE | \ OB_PRIV_ALTER_TENANT | OB_PRIV_ALTER_SYSTEM | \ OB_PRIV_CREATE_RESOURCE_POOL | OB_PRIV_CREATE_RESOURCE_UNIT| \ - OB_PRIV_REPL_SLAVE | OB_PRIV_REPL_CLIENT) + OB_PRIV_REPL_SLAVE | OB_PRIV_REPL_CLIENT | \ + OB_PRIV_DROP_DATABASE_LINK | OB_PRIV_CREATE_DATABASE_LINK) #define OB_PRIV_DB_ACC \ (OB_PRIV_ALTER | OB_PRIV_CREATE | OB_PRIV_DELETE | \ diff --git a/src/share/schema/ob_schema_getter_guard.cpp b/src/share/schema/ob_schema_getter_guard.cpp index a50810c1e7..89b2a96ccb 100644 --- a/src/share/schema/ob_schema_getter_guard.cpp +++ b/src/share/schema/ob_schema_getter_guard.cpp @@ -8418,7 +8418,8 @@ int ObSchemaGetterGuard::get_link_table_schema( ObTableSchema *&table_schema, sql::ObSQLSessionInfo *session_info, const ObString &dblink_name, - bool is_reverse_link) + bool is_reverse_link, + uint64_t *current_scn) { int ret = OB_SUCCESS; const ObDbLinkSchema *dblink_schema = NULL; @@ -8434,7 +8435,8 @@ int ObSchemaGetterGuard::get_link_table_schema( database_name, table_name, allocator, table_schema, session_info, dblink_name, - is_reverse_link))) { + is_reverse_link, + current_scn))) { LOG_WARN("get link table schema failed", KR(ret)); } LOG_DEBUG("get link table schema", K(is_reverse_link), KP(dblink_schema), K(ret)); diff --git a/src/share/schema/ob_schema_getter_guard.h b/src/share/schema/ob_schema_getter_guard.h index 9b578dc294..cd0aef61e9 100644 --- a/src/share/schema/ob_schema_getter_guard.h +++ b/src/share/schema/ob_schema_getter_guard.h @@ -918,7 +918,8 @@ public: ObTableSchema *&table_schema, sql::ObSQLSessionInfo *session_info, const ObString &dblink_name, - bool is_reverse_link); + bool is_reverse_link, + uint64_t *current_scn); // dblink function end // directory function begin diff --git a/src/share/schema/ob_schema_retrieve_utils.ipp b/src/share/schema/ob_schema_retrieve_utils.ipp index e0ac3c5792..e9975ef40c 100644 --- a/src/share/schema/ob_schema_retrieve_utils.ipp +++ b/src/share/schema/ob_schema_retrieve_utils.ipp @@ -44,6 +44,15 @@ namespace schema } \ } +#define EXTRACT_PRIV_FROM_MYSQL_RESULT_IGNORE_NULL_AND_IGNORE_COLUMN_ERROR(result, column_name, obj, priv_type) \ + if (OB_SUCC(ret)) { \ + int64_t priv_col_value = 0; \ + EXTRACT_INT_FIELD_MYSQL_WITH_DEFAULT_VALUE(result, #column_name, priv_col_value, int64_t, true, true, 0) \ + if (OB_SUCC(ret)) { \ + 1 == priv_col_value ? (obj).set_priv(OB_##priv_type) : (void) 0; \ + } \ + } + #define EXTRACT_PRIV_FIELD_FROM_MYSQL_RESULT(result, column_name, priv_set, priv_type) \ if (OB_SUCC(ret)) { \ int64_t int_value = 0; \ @@ -1636,6 +1645,8 @@ int ObSchemaRetrieveUtils::fill_user_schema( EXTRACT_INT_FIELD_TO_CLASS_MYSQL_WITH_DEFAULT_VALUE( result, max_user_connections, user_info, uint64_t, true, ObSchemaService::g_ignore_column_retrieve_error_, 0); + EXTRACT_PRIV_FROM_MYSQL_RESULT_IGNORE_NULL_AND_IGNORE_COLUMN_ERROR(result, priv_drop_database_link, user_info, PRIV_DROP_DATABASE_LINK); + EXTRACT_PRIV_FROM_MYSQL_RESULT_IGNORE_NULL_AND_IGNORE_COLUMN_ERROR(result, priv_create_database_link, user_info, PRIV_CREATE_DATABASE_LINK); } return ret; } @@ -1982,6 +1993,7 @@ int ObSchemaRetrieveUtils::fill_dblink_schema( dblink_schema.reset(); is_deleted = false; int ret = common::OB_SUCCESS; + bool is_oracle_mode = false; ObString default_val(""); dblink_schema.set_tenant_id(tenant_id); EXTRACT_INT_FIELD_TO_CLASS_MYSQL_WITH_TENANT_ID(result, dblink_id, dblink_schema, tenant_id); @@ -2018,11 +2030,18 @@ int ObSchemaRetrieveUtils::fill_dblink_schema( EXTRACT_VARCHAR_FIELD_TO_CLASS_MYSQL_WITH_DEFAULT_VALUE(result, reverse_tenant_name, dblink_schema, true, skip_column_error, default_val); EXTRACT_VARCHAR_FIELD_TO_CLASS_MYSQL_WITH_DEFAULT_VALUE(result, reverse_user_name, dblink_schema, true, skip_column_error, default_val); EXTRACT_VARCHAR_FIELD_TO_CLASS_MYSQL_WITH_DEFAULT_VALUE(result, reverse_password, dblink_schema, true, skip_column_error, default_val); + EXTRACT_VARCHAR_FIELD_TO_CLASS_MYSQL_WITH_DEFAULT_VALUE(result, database_name, dblink_schema, true, skip_column_error, default_val); if (OB_FAIL(ret)) { } else if (OB_FAIL(dblink_schema.do_decrypt_password())) { LOG_WARN("failed to decrypt password", K(ret)); } else if (OB_FAIL(dblink_schema.do_decrypt_reverse_password())) { LOG_WARN("failed to decrypt reverse_password", K(ret)); + } else if (OB_FAIL(ObCompatModeGetter::check_is_oracle_mode_with_tenant_id( + tenant_id, is_oracle_mode))) { + LOG_WARN("fail to check is oracle mode", K(tenant_id), K(ret)); + } else if (!is_oracle_mode && dblink_schema.get_database_name().empty()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("mysql dblink database_name is empty", K(ret)); } } return ret; diff --git a/src/share/schema/ob_schema_service.h b/src/share/schema/ob_schema_service.h index 28daa06e94..ffcde8b698 100644 --- a/src/share/schema/ob_schema_service.h +++ b/src/share/schema/ob_schema_service.h @@ -1121,7 +1121,8 @@ public: ObTableSchema *&table_schema, sql::ObSQLSessionInfo *session_info, const common::ObString &dblink_name, - bool is_reverse_link) = 0; + bool is_reverse_link, + uint64_t *current_scn) = 0; // when refresh schema, if new ddl operations are as following: // (ALTER USER TABLE, v1), (ALTER SYS TABLE, v2), // if we replay new ddl operation one by one, when we execute sql to read sys table diff --git a/src/share/schema/ob_schema_service_sql_impl.cpp b/src/share/schema/ob_schema_service_sql_impl.cpp index 7bfbc8179d..c0ff882190 100644 --- a/src/share/schema/ob_schema_service_sql_impl.cpp +++ b/src/share/schema/ob_schema_service_sql_impl.cpp @@ -42,6 +42,7 @@ #include "share/schema/ob_server_schema_service.h" #include "sql/ob_sql_utils.h" #include "sql/session/ob_sql_session_mgr.h" +#include "common/sql_mode/ob_sql_mode_utils.h" #define COMMON_SQL "SELECT * FROM %s" #define COMMON_SQL_WITH_TENANT "SELECT * FROM %s WHERE tenant_id = %lu" @@ -8272,7 +8273,8 @@ int ObSchemaServiceSQLImpl::get_link_table_schema(const ObDbLinkSchema *dblink_s ObTableSchema *&table_schema, sql::ObSQLSessionInfo *session_info, const ObString &dblink_name, - bool is_reverse_link) + bool is_reverse_link, + uint64_t *current_scn) { int ret = OB_SUCCESS; ObTableSchema *tmp_schema = NULL; @@ -8342,7 +8344,7 @@ int ObSchemaServiceSQLImpl::get_link_table_schema(const ObDbLinkSchema *dblink_s } else if (OB_FAIL(fetch_link_table_info(tenant_id, dblink_id, link_type, conn_type, database_name, table_name, alloctor, tmp_schema, session_info, dblink_name_for_meta, reverse_link, param_ctx, - next_sql_req_level))) { + next_sql_req_level, current_scn))) { LOG_WARN("fetch link table info failed", K(ret), K(dblink_schema), K(database_name), K(table_name)); } else if (OB_ISNULL(tmp_schema)) { ret = OB_ERR_UNEXPECTED; @@ -8371,18 +8373,25 @@ int ObSchemaServiceSQLImpl::fetch_link_table_info(uint64_t tenant_id, const ObString &dblink_name, sql::ObReverseLink *reverse_link, const dblink_param_ctx ¶m_ctx, - int64_t &next_sql_req_level) + int64_t &next_sql_req_level, + uint64_t *current_scn) { int ret = OB_SUCCESS; int dblink_read_ret = OB_SUCCESS; const char *dblink_read_errmsg = NULL; ObMySQLResult *result = NULL; ObSqlString sql; - static const char * sql_str_fmt_array[] = { + const char *set_sql_mode_sql = NULL; + static const char * sql_str_fmt_array[] = { // for Oracle mode dblink "/*$BEFPARSEdblink_req_level=1*/ SELECT * FROM \"%.*s\".\"%.*s\"%c%.*s WHERE ROWNUM < 1", "/*$BEFPARSEdblink_req_level=2*/ SELECT * FROM \"%.*s\".\"%.*s\"%c%.*s WHERE ROWNUM < 1", "/*$BEFPARSEdblink_req_level=3*/ SELECT * FROM \"%.*s\".\"%.*s\"%c%.*s WHERE ROWNUM < 1", }; + static const char * sql_str_fmt_array_mysql_mode[] = { // for MySql mode dblink + "/*$BEFPARSEdblink_req_level=1*/ SELECT * FROM `%.*s`.`%.*s`%c%.*s LIMIT 0", + "/*$BEFPARSEdblink_req_level=2*/ SELECT * FROM `%.*s`.`%.*s`%c%.*s LIMIT 0", + "/*$BEFPARSEdblink_req_level=3*/ SELECT * FROM `%.*s`.`%.*s`%c%.*s LIMIT 0", + }; SMART_VAR(ObMySQLProxy::MySQLResult, res) { common::sqlclient::ObISQLConnection *dblink_conn = NULL; if (NULL == session_info) { @@ -8391,12 +8400,14 @@ int ObSchemaServiceSQLImpl::fetch_link_table_info(uint64_t tenant_id, } else if (database_name.empty() || table_name.empty()) { ret = OB_INVALID_ARGUMENT; LOG_WARN("table name or database name is empty", K(ret), K(database_name), K(table_name)); - } else if (OB_FAIL(sql.append_fmt(sql_str_fmt_array[next_sql_req_level - 1], + } else if (OB_FAIL(sql.append_fmt(lib::is_oracle_mode() ? + sql_str_fmt_array[next_sql_req_level - 1] : + sql_str_fmt_array_mysql_mode[next_sql_req_level - 1], database_name.length(), database_name.ptr(), table_name.length(), table_name.ptr(), dblink_name.empty() ? ' ' : '@', dblink_name.length(), dblink_name.ptr()))) { - LOG_WARN("append sql failed", K(ret)); + LOG_WARN("append sql failed", K(ret), K(database_name), K(table_name), K(dblink_name)); } else if (sql::DblinkGetConnType::TEMP_CONN == conn_type) { if (OB_ISNULL(reverse_link)) { ret = OB_ERR_UNEXPECTED; @@ -8406,13 +8417,17 @@ int ObSchemaServiceSQLImpl::fetch_link_table_info(uint64_t tenant_id, } else { LOG_DEBUG("succ to read table meta by reverse_link"); } - } else if (OB_FAIL(dblink_proxy_->acquire_dblink(dblink_id, link_type, param_ctx, dblink_conn, session_info->get_sessid(), next_sql_req_level))) { - ObDblinkUtils::process_dblink_errno(link_type, ret); + } else if (!is_oracle_mode() && OB_FAIL(ObDblinkService::get_set_sql_mode_cstr(session_info, set_sql_mode_sql, alloctor))) { + LOG_WARN("failed to get set_sql_mode_sql", K(ret)); + } else if (OB_FAIL(dblink_proxy_->acquire_dblink(dblink_id, link_type, param_ctx, + dblink_conn, + session_info->get_sessid(), + next_sql_req_level, + set_sql_mode_sql))) { LOG_WARN("failed to acquire dblink", K(ret), K(dblink_id)); } else if (OB_FAIL(session_info->get_dblink_context().register_dblink_conn_pool(dblink_conn->get_common_server_pool()))) { LOG_WARN("failed to register dblink conn pool to current session", K(ret)); } else if (OB_FAIL(dblink_proxy_->dblink_read(dblink_conn, res, sql.ptr()))) { - ObDblinkUtils::process_dblink_errno(link_type, dblink_conn, ret); LOG_WARN("read link failed", K(ret), K(dblink_id), K(sql.ptr())); } if (OB_FAIL(ret)) { @@ -8424,129 +8439,24 @@ int ObSchemaServiceSQLImpl::fetch_link_table_info(uint64_t tenant_id, static_cast(common::ObNlsCharsetId::CHARSET_AL32UTF8_ID)))) { // dblink will convert the result to AL32UTF8 when pulling schema meta LOG_WARN("failed to set expected charset id", K(ret)); - } else { - const char * desc_sql_str_fmt = "/*$BEFPARSEdblink_req_level=1*/ desc \"%.*s\".\"%.*s\""; - ObSqlString desc_sql; - ObMySQLResult *desc_result = NULL; - bool need_desc = (next_sql_req_level == 1) && DBLINK_DRV_OB == link_type && sql::DblinkGetConnType::TEMP_CONN != conn_type; - int64_t desc_res_row_idx = -1; - SMART_VAR(ObMySQLProxy::MySQLResult, desc_res) { - T tmp_table_schema; - table_schema = NULL; - ObObjMeta type; - int64_t column_count = result->get_column_count(); - tmp_table_schema.set_tenant_id(tenant_id); - tmp_table_schema.set_table_id(1); //no use - tmp_table_schema.set_dblink_id(dblink_id); - tmp_table_schema.set_collation_type(CS_TYPE_UTF8MB4_BIN); - tmp_table_schema.set_charset_type(ObCharset::charset_type_by_coll(tmp_table_schema.get_collation_type())); - if (OB_FAIL(ret)) { - // do nothing - } else if (OB_FAIL(tmp_table_schema.set_table_name(table_name))) { - LOG_WARN("set table name failed", K(ret), K(table_name)); - } else if (OB_FAIL(tmp_table_schema.set_link_database_name(database_name))) { - LOG_WARN("set database name failed", K(ret), K(database_name)); - } - for (int64_t i = 0; OB_SUCC(ret) && i < column_count; ++i) { - ObColumnSchemaV2 column_schema; - int16_t precision = 0; - int16_t scale = 0; - int32_t length = 0; - ObString column_name; - bool old_max_length = false; - ObAccuracy acc; - if (OB_FAIL(result->get_col_meta(i, old_max_length, column_name, type, acc))) { - LOG_WARN("failed to get column meta", K(i), K(old_max_length), K(ret)); - } else if (OB_FAIL(column_schema.set_column_name(column_name))) { - LOG_WARN("failed to set column name", K(i), K(column_name), K(ret)); - } else { - precision = acc.get_precision(); - scale = acc.get_scale(); - length = acc.get_length(); - column_schema.set_table_id(tmp_table_schema.get_table_id()); - column_schema.set_tenant_id(tenant_id); - column_schema.set_column_id(i + OB_END_RESERVED_COLUMN_ID_NUM); - column_schema.set_meta_type(type); - column_schema.set_charset_type(ObCharset::charset_type_by_coll(column_schema.get_collation_type())); - column_schema.set_data_precision(precision); - column_schema.set_data_scale(scale); - LOG_DEBUG("schema service sql impl get DBLINK schema", K(column_schema), K(length)); - if (need_desc && OB_ISNULL(desc_result) && - (ObNCharType == column_schema.get_data_type() || ObNVarchar2Type == column_schema.get_data_type())) { - if (OB_FAIL(desc_sql.append_fmt(desc_sql_str_fmt, database_name.length(), database_name.ptr(), - table_name.length(), table_name.ptr()))) { - LOG_WARN("append desc sql failed", K(ret)); - } else if (OB_FAIL(dblink_proxy_->dblink_read(dblink_conn, desc_res, desc_sql.ptr()))) { - ObDblinkUtils::process_dblink_errno(link_type, dblink_conn, ret); - LOG_WARN("read link failed", K(ret), K(dblink_id), K(desc_sql.ptr())); - } else if (OB_ISNULL(desc_result = desc_res.get_result())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("fail to get result", K(ret)); - } else if (OB_FAIL(desc_result->set_expected_charset_id(static_cast(common::ObNlsCharsetId::CHARSET_AL32UTF8_ID), - static_cast(common::ObNlsCharsetId::CHARSET_AL32UTF8_ID)))) { - // dblink will convert the result to AL32UTF8 when pulling schema meta - LOG_WARN("failed to set expected charset id", K(ret)); - } - } - if (OB_SUCC(ret) && OB_NOT_NULL(desc_result) && (ObNCharType == column_schema.get_data_type() || ObNVarchar2Type == column_schema.get_data_type())) { - while (OB_SUCC(ret) && desc_res_row_idx < i) { - if (OB_FAIL(desc_result->next())) { - LOG_WARN("failed to get next row", K(ret)); - } - ++desc_res_row_idx; - } - if (desc_res_row_idx == i && OB_SUCC(ret)) { - const ObTimeZoneInfo *tz_info = TZ_INFO(session_info); - ObObj value; - ObString string_value; - if (OB_ISNULL(tz_info)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("tz info is NULL", K(ret)); - } else if (OB_FAIL(desc_result->get_obj(1, value, tz_info, &alloctor))) { - LOG_WARN("failed to get obj", K(ret)); - } else if (ObVarcharType != value.get_type()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("type is invalid", K(value.get_type()), K(ret)); - } else if (OB_FAIL(value.get_varchar(string_value))) { - LOG_WARN("failed to get varchar value", K(ret)); - } else if (OB_FAIL(ObDblinkService::get_length_from_type_text(string_value, length))) { - LOG_WARN("failed to get length", K(ret)); - } else { - LOG_DEBUG("desc table type string", K(string_value), K(length)); - } - } - } - column_schema.set_data_length(length); - } - LOG_DEBUG("dblink column schema", K(i), K(column_schema.get_data_precision()), - K(column_schema.get_data_scale()), - K(column_schema.get_data_length()), - K(column_schema.get_data_type())); - if (OB_SUCC(ret) && OB_FAIL(tmp_table_schema.add_column(column_schema))) { - LOG_WARN("fail to add link column schema. ", K(i), K(column_schema), K(ret)); - } - } - if (OB_SUCC(ret) && OB_FAIL(ObSchemaUtils::alloc_schema(alloctor, tmp_table_schema, table_schema))) { - LOG_WARN("failed to alloc table_schema", K(ret)); - } - int tmp_ret = OB_SUCCESS; - if (OB_NOT_NULL(desc_result) && OB_SUCCESS != (tmp_ret = desc_result->close())) { - LOG_WARN("failed to close desc result", K(tmp_ret)); - } else { - desc_result = NULL; - } - } - } - if (OB_FAIL(ret)) { - //do nothing + } else if (OB_FAIL(generate_link_table_schema(tenant_id, dblink_id, link_type, conn_type, + database_name, table_name, alloctor, table_schema, session_info, + dblink_conn, result, next_sql_req_level))) { + LOG_WARN("generate link table schema failed", K(ret)); } else if (OB_ISNULL(table_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null ptr"); - } else if (OB_FAIL(try_mock_link_table_column(*table_schema))) { + } else if (lib::is_oracle_mode() && OB_FAIL(try_mock_link_table_column(*table_schema))) { LOG_WARN("failed to mock link table pkey", K(ret)); } else { table_schema->set_table_organization_mode(ObTableOrganizationMode::TOM_HEAP_ORGANIZED); } + if (OB_SUCC(ret) && DBLINK_DRV_OB == link_type && NULL != current_scn) { + if (OB_FAIL(fetch_link_current_scn(tenant_id, dblink_id, conn_type, alloctor, dblink_conn, + reverse_link, next_sql_req_level, *current_scn))) { + LOG_WARN("fetch link current scn failed", K(ret)); + } + } if (NULL != dblink_conn) { int tmp_ret = OB_SUCCESS; if (DBLINK_DRV_OB == link_type && @@ -8565,6 +8475,208 @@ int ObSchemaServiceSQLImpl::fetch_link_table_info(uint64_t tenant_id, return ret; } +template +int ObSchemaServiceSQLImpl::generate_link_table_schema(uint64_t tenant_id, uint64_t dblink_id, + DblinkDriverProto link_type, + sql::DblinkGetConnType conn_type, + const ObString &database_name, + const ObString &table_name, + ObIAllocator &allocator, + T *&table_schema, + const sql::ObSQLSessionInfo *session_info, + common::sqlclient::ObISQLConnection *dblink_conn, + const ObMySQLResult *col_meta_result, + int64_t &next_sql_req_level) +{ + int ret = OB_SUCCESS; + const char * desc_sql_str_fmt = "/*$BEFPARSEdblink_req_level=1*/ desc \"%.*s\".\"%.*s\""; + ObSqlString desc_sql; + int64_t desc_res_row_idx = -1; + bool need_desc = (next_sql_req_level == 1) && DBLINK_DRV_OB == link_type + && sql::DblinkGetConnType::TEMP_CONN != conn_type; + ObMySQLResult *desc_result = NULL; + SMART_VAR(ObMySQLProxy::MySQLResult, desc_res) { + T tmp_table_schema; + table_schema = NULL; + ObObjMeta type; + int64_t column_count = col_meta_result->get_column_count(); + tmp_table_schema.set_tenant_id(tenant_id); + tmp_table_schema.set_table_id(1); //no use + tmp_table_schema.set_dblink_id(dblink_id); + tmp_table_schema.set_collation_type(CS_TYPE_UTF8MB4_BIN); + tmp_table_schema.set_charset_type(ObCharset::charset_type_by_coll(tmp_table_schema.get_collation_type())); + if (OB_FAIL(tmp_table_schema.set_table_name(table_name))) { + LOG_WARN("set table name failed", K(ret), K(table_name)); + } else if (OB_FAIL(tmp_table_schema.set_link_database_name(database_name))) { + LOG_WARN("set database name failed", K(ret), K(database_name)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < column_count; ++i) { + ObColumnSchemaV2 column_schema; + int16_t precision = 0; + int16_t scale = 0; + int32_t length = 0; + ObString column_name; + bool old_max_length = false; + ObAccuracy acc; + if (OB_FAIL(col_meta_result->get_col_meta(i, old_max_length, column_name, type, acc))) { + LOG_WARN("failed to get column meta", K(i), K(old_max_length), K(ret)); + } else if (OB_FAIL(column_schema.set_column_name(column_name))) { + LOG_WARN("failed to set column name", K(i), K(column_name), K(ret)); + } else { + precision = acc.get_precision(); + scale = acc.get_scale(); + length = acc.get_length(); + column_schema.set_table_id(tmp_table_schema.get_table_id()); + column_schema.set_tenant_id(tenant_id); + column_schema.set_column_id(i + OB_END_RESERVED_COLUMN_ID_NUM); + column_schema.set_meta_type(type); + column_schema.set_charset_type(ObCharset::charset_type_by_coll(column_schema.get_collation_type())); + column_schema.set_data_precision(precision); + column_schema.set_data_scale(scale); + LOG_DEBUG("schema service sql impl get DBLINK schema", K(column_schema), K(length)); + if (need_desc && OB_ISNULL(desc_result) && + (ObNCharType == column_schema.get_data_type() + || ObNVarchar2Type == column_schema.get_data_type())) { + if (OB_ISNULL(dblink_conn)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dblink conn is null",K(ret)); + } else if (OB_FAIL(desc_sql.append_fmt(desc_sql_str_fmt, database_name.length(), + database_name.ptr(), table_name.length(), table_name.ptr()))) { + LOG_WARN("append desc sql failed", K(ret)); + } else if (OB_FAIL(dblink_proxy_->dblink_read(dblink_conn, desc_res, desc_sql.ptr()))) { + LOG_WARN("read link failed", K(ret), K(dblink_id), K(desc_sql.ptr())); + } else if (OB_ISNULL(desc_result = desc_res.get_result())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("fail to get result", K(ret)); + } else if (OB_FAIL(desc_result->set_expected_charset_id(static_cast(common::ObNlsCharsetId::CHARSET_AL32UTF8_ID), + static_cast(common::ObNlsCharsetId::CHARSET_AL32UTF8_ID)))) { + // dblink will convert the result to AL32UTF8 when pulling schema meta + LOG_WARN("failed to set expected charset id", K(ret)); + } + } + if (OB_SUCC(ret) && OB_NOT_NULL(desc_result) + &&(ObNCharType == column_schema.get_data_type() + || ObNVarchar2Type == column_schema.get_data_type())) { + while (OB_SUCC(ret) && desc_res_row_idx < i) { + if (OB_FAIL(desc_result->next())) { + LOG_WARN("failed to get next row", K(ret)); + } + ++desc_res_row_idx; + } + if (desc_res_row_idx == i && OB_SUCC(ret)) { + const ObTimeZoneInfo *tz_info = TZ_INFO(session_info); + ObObj value; + ObString string_value; + if (OB_ISNULL(tz_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("tz info is NULL", K(ret)); + } else if (OB_FAIL(desc_result->get_obj(1, value, tz_info, &allocator))) { + LOG_WARN("failed to get obj", K(ret)); + } else if (ObVarcharType != value.get_type()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("type is invalid", K(value.get_type()), K(ret)); + } else if (OB_FAIL(value.get_varchar(string_value))) { + LOG_WARN("failed to get varchar value", K(ret)); + } else if (OB_FAIL(ObDblinkService::get_length_from_type_text(string_value, length))) { + LOG_WARN("failed to get length", K(ret)); + } else { + LOG_DEBUG("desc table type string", K(string_value), K(length)); + } + } + } + column_schema.set_data_length(length); + } + LOG_DEBUG("dblink column schema", K(i), K(column_schema.get_data_precision()), + K(column_schema.get_data_scale()), + K(column_schema.get_data_length()), + K(column_schema.get_data_type())); + if (OB_SUCC(ret) && OB_FAIL(tmp_table_schema.add_column(column_schema))) { + LOG_WARN("fail to add link column schema. ", K(i), K(column_schema), K(ret)); + } + } + if (OB_SUCC(ret) && OB_FAIL(ObSchemaUtils::alloc_schema(allocator, tmp_table_schema, table_schema))) { + LOG_WARN("failed to alloc table_schema", K(ret)); + } + int tmp_ret = OB_SUCCESS; + if (OB_NOT_NULL(desc_result) && OB_SUCCESS != (tmp_ret = desc_result->close())) { + LOG_WARN("failed to close desc result", K(tmp_ret)); + } else { + desc_result = NULL; + } + } + return ret; +} + +int ObSchemaServiceSQLImpl::fetch_link_current_scn(uint64_t tenant_id, + uint64_t dblink_id, + sql::DblinkGetConnType conn_type, + ObIAllocator &allocator, + common::sqlclient::ObISQLConnection *dblink_conn, + sql::ObReverseLink *reverse_link, + int64_t next_sql_req_level, + uint64_t ¤t_scn) +{ + int ret = OB_SUCCESS; + static const char * sql_str_fmt_array[] = { + "/*$BEFPARSEdblink_req_level=1*/ SELECT current_scn() FROM dual", + "/*$BEFPARSEdblink_req_level=2*/ SELECT current_scn() FROM dual", + "/*$BEFPARSEdblink_req_level=3*/ SELECT current_scn() FROM dual", + }; + SMART_VAR(ObMySQLProxy::MySQLResult, res) { + ObSqlString sql; + ObMySQLResult *result = NULL; + if (OB_UNLIKELY(next_sql_req_level <= 0 || next_sql_req_level > 3)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected sql req level", K(ret), K(next_sql_req_level)); + } else if (OB_FAIL(sql.assign(sql_str_fmt_array[next_sql_req_level - 1]))) { + LOG_WARN("append sql failed",K(ret)); + } else if (sql::DblinkGetConnType::TEMP_CONN == conn_type) { + if (OB_ISNULL(reverse_link)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("reverse_link is NULL", K(ret)); + } else if (OB_FAIL(reverse_link->read(sql.ptr(), res))) { + LOG_WARN("failed to read table meta by reverse_link", K(ret)); + ret = OB_SUCCESS; + } else { + result = res.get_result(); + } + } else if (OB_ISNULL(dblink_conn)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("link conn is NULL", K(ret)); + } else if (OB_FAIL(dblink_proxy_->dblink_read(dblink_conn, res, sql.ptr()))) { + LOG_WARN("read link failed", K(ret), K(dblink_id), K(sql.ptr())); + ret = OB_SUCCESS; + } else { + result = res.get_result(); + } + if (OB_SUCC(ret) && OB_NOT_NULL(result)) { + ObNumber scn_num; + ObObj value; + int64_t col_idx = 0; + if (OB_FAIL(result->next())) { + LOG_WARN("failed to get next row", K(ret)); + } else if (OB_FAIL(result->get_obj(col_idx, value, NULL /* tz_info */, &allocator))) { + LOG_WARN("get obj failed", K(ret)); + } else if (value.is_number()) { + if (OB_FAIL(value.get_number(scn_num))) { + LOG_WARN("get number failed", K(ret)); + } else if (OB_UNLIKELY(!scn_num.is_valid_uint64(current_scn))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected value value", K(ret), K(value)); + } + } else if (OB_LIKELY(value.is_uint64())) { + current_scn = value.get_uint64(); + } else if (value.is_int()) { + current_scn = value.get_int(); + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected value type", K(ret), K(value)); + } + } + } + return ret; +} + int ObSchemaServiceSQLImpl::try_mock_link_table_column(ObTableSchema &table_schema) { int ret = OB_SUCCESS; diff --git a/src/share/schema/ob_schema_service_sql_impl.h b/src/share/schema/ob_schema_service_sql_impl.h index dd5944e837..d6c636b59c 100644 --- a/src/share/schema/ob_schema_service_sql_impl.h +++ b/src/share/schema/ob_schema_service_sql_impl.h @@ -577,7 +577,8 @@ public: ObTableSchema *&table_schema, sql::ObSQLSessionInfo *session_info, const ObString &dblink_name, - bool is_reverse_link); + bool is_reverse_link, + uint64_t *current_scn); static int check_ddl_id_exist( common::ObISQLClient &sql_client, @@ -880,7 +881,28 @@ private: const ObString &dblink_name, sql::ObReverseLink *reverse_link, const common::sqlclient::dblink_param_ctx ¶m_ctx, - int64_t &next_sql_req_level); + int64_t &next_sql_req_level, + uint64_t *current_scn); + template + int generate_link_table_schema(uint64_t tenant_id, uint64_t dblink_id, + common::sqlclient::DblinkDriverProto link_type, + sql::DblinkGetConnType conn_type, + const ObString &database_name, + const ObString &table_name, + ObIAllocator &allocator, + T *&table_schema, + const sql::ObSQLSessionInfo *session_info, + common::sqlclient::ObISQLConnection *dblink_conn, + const common::sqlclient::ObMySQLResult *col_meta_result, + int64_t &next_sql_req_level); + int fetch_link_current_scn(uint64_t tenant_id, + uint64_t dblink_id, + sql::DblinkGetConnType conn_type, + ObIAllocator &allocator, + common::sqlclient::ObISQLConnection *dblink_conn, + sql::ObReverseLink *reverse_link, + int64_t next_sql_req_level, + uint64_t ¤t_scn); int try_mock_link_table_column(ObTableSchema &table_schema); template diff --git a/src/share/schema/ob_schema_struct.cpp b/src/share/schema/ob_schema_struct.cpp index b71800e6ac..97cb061be6 100644 --- a/src/share/schema/ob_schema_struct.cpp +++ b/src/share/schema/ob_schema_struct.cpp @@ -8023,6 +8023,12 @@ DEF_TO_STRING(ObPrintPrivSet) if ((priv_set_ & OB_PRIV_REPL_CLIENT) && OB_SUCCESS == ret) { ret = BUF_PRINTF(" REPLICATION CLIENT,"); } + if ((priv_set_ & OB_PRIV_DROP_DATABASE_LINK) && OB_SUCCESS == ret) { + ret = BUF_PRINTF(" DROP DATABASE LINK,"); + } + if ((priv_set_ & OB_PRIV_CREATE_DATABASE_LINK) && OB_SUCCESS == ret) { + ret = BUF_PRINTF(" CREATE DATABASE LINK,"); + } if (OB_SUCCESS == ret && pos > 1) { pos--; //Delete last ',' } @@ -10097,6 +10103,7 @@ void ObDbLinkBaseInfo::reset() plain_password_.reset(); host_addr_.reset(); driver_proto_ = 0; + if_not_exist_ = false; flag_ = 0; service_name_.reset(); conn_string_.reset(); @@ -10110,6 +10117,7 @@ void ObDbLinkBaseInfo::reset() reverse_password_.reset(); plain_reverse_password_.reset(); reverse_host_addr_.reset(); + database_name_.reset(); } bool ObDbLinkBaseInfo::is_valid() const @@ -10226,7 +10234,9 @@ OB_SERIALIZE_MEMBER(ObDbLinkInfo, reverse_user_name_, reverse_password_, plain_reverse_password_, - reverse_host_addr_); + reverse_host_addr_, + database_name_, + if_not_exist_); ObDbLinkSchema::ObDbLinkSchema(const ObDbLinkSchema &other) : ObDbLinkBaseInfo() @@ -10246,6 +10256,7 @@ ObDbLinkSchema &ObDbLinkSchema::operator=(const ObDbLinkSchema &other) dblink_id_ = other.dblink_id_; schema_version_ = other.schema_version_; driver_proto_ = other.driver_proto_; + if_not_exist_ = other.if_not_exist_; flag_ = other.flag_; if (OB_FAIL(deep_copy_str(other.dblink_name_, dblink_name_))) { LOG_WARN("Fail to deep copy dblink name", K(ret)); @@ -10258,31 +10269,33 @@ ObDbLinkSchema &ObDbLinkSchema::operator=(const ObDbLinkSchema &other) } else if (OB_FAIL(deep_copy_str(other.password_, password_))) { LOG_WARN("Fail to deep copy password", K(ret), K(other.password_)); } else if (OB_FAIL(deep_copy_str(other.encrypted_password_, encrypted_password_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.encrypted_password_)); + LOG_WARN("Fail to deep copy encrypted_password", K(ret), K(other.encrypted_password_)); } else if (OB_FAIL(deep_copy_str(other.plain_password_, plain_password_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.plain_password_)); + LOG_WARN("Fail to deep copy plain_password", K(ret), K(other.plain_password_)); } else if (OB_FAIL(deep_copy_str(other.service_name_, service_name_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.service_name_)); + LOG_WARN("Fail to deep copy service_name", K(ret), K(other.service_name_)); } else if (OB_FAIL(deep_copy_str(other.conn_string_, conn_string_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.conn_string_)); + LOG_WARN("Fail to deep copy conn_string", K(ret), K(other.conn_string_)); } else if (OB_FAIL(deep_copy_str(other.authusr_, authusr_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.authusr_)); + LOG_WARN("Fail to deep copy authusr", K(ret), K(other.authusr_)); } else if (OB_FAIL(deep_copy_str(other.authpwd_, authpwd_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.authpwd_)); + LOG_WARN("Fail to deep copy authpwd", K(ret), K(other.authpwd_)); } else if (OB_FAIL(deep_copy_str(other.passwordx_, passwordx_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.passwordx_)); + LOG_WARN("Fail to deep copy passwordx", K(ret), K(other.passwordx_)); } else if (OB_FAIL(deep_copy_str(other.authpwdx_, authpwdx_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.authpwdx_)); + LOG_WARN("Fail to deep copy authpwdx", K(ret), K(other.authpwdx_)); } else if (OB_FAIL(deep_copy_str(other.reverse_cluster_name_, reverse_cluster_name_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.reverse_cluster_name_)); + LOG_WARN("Fail to deep copy reverse_cluster_name", K(ret), K(other.reverse_cluster_name_)); } else if (OB_FAIL(deep_copy_str(other.reverse_tenant_name_, reverse_tenant_name_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.reverse_tenant_name_)); + LOG_WARN("Fail to deep copy reverse_tenant_name", K(ret), K(other.reverse_tenant_name_)); } else if (OB_FAIL(deep_copy_str(other.reverse_user_name_, reverse_user_name_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.reverse_user_name_)); + LOG_WARN("Fail to deep copy reverse_user_name", K(ret), K(other.reverse_user_name_)); } else if (OB_FAIL(deep_copy_str(other.reverse_password_, reverse_password_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.reverse_password_)); + LOG_WARN("Fail to deep copy reverse_password", K(ret), K(other.reverse_password_)); } else if (OB_FAIL(deep_copy_str(other.plain_reverse_password_, plain_reverse_password_))) { - LOG_WARN("Fail to deep copy password", K(ret), K(other.plain_reverse_password_)); + LOG_WARN("Fail to deep copy plain_reverse_password", K(ret), K(other.plain_reverse_password_)); + } else if (OB_FAIL(deep_copy_str(other.database_name_, database_name_))) { + LOG_WARN("Fail to deep copy database_name", K(ret), K(other.database_name_)); } host_addr_ = other.host_addr_; reverse_host_addr_ = other.reverse_host_addr_; @@ -10320,7 +10333,9 @@ bool ObDbLinkSchema::operator==(const ObDbLinkSchema &other) const && reverse_user_name_ == other.reverse_user_name_ && reverse_password_ == other.reverse_password_ && plain_reverse_password_ == other.plain_reverse_password_ - && reverse_host_addr_ == other.reverse_host_addr_); + && reverse_host_addr_ == other.reverse_host_addr_ + && database_name_ == other.database_name_ + && if_not_exist_ == other.if_not_exist_); } ObSynonymInfo::ObSynonymInfo(common::ObIAllocator *allocator): diff --git a/src/share/schema/ob_schema_struct.h b/src/share/schema/ob_schema_struct.h index e422721780..ec565a81fd 100644 --- a/src/share/schema/ob_schema_struct.h +++ b/src/share/schema/ob_schema_struct.h @@ -5008,6 +5008,7 @@ public: inline void set_host_addr(const common::ObAddr &addr) { host_addr_ = addr; } int set_host_ip(const common::ObString &host_ip); inline void set_host_port(const int32_t host_port) { host_addr_.set_port(host_port); } + inline int set_database_name(const common::ObString &name) { return deep_copy_str(name, database_name_); } inline int set_reverse_cluster_name(const common::ObString &name) { return deep_copy_str(name, reverse_cluster_name_); } inline int set_reverse_tenant_name(const common::ObString &name) { return deep_copy_str(name, reverse_tenant_name_); } inline int set_reverse_user_name(const common::ObString &name) { return deep_copy_str(name, reverse_user_name_); } @@ -5039,6 +5040,7 @@ public: inline const common::ObString &get_plain_password() const { return plain_password_; } inline const common::ObAddr &get_host_addr() const { return host_addr_; } inline int32_t get_host_port() const { return host_addr_.get_port(); } + inline const common::ObString &get_database_name() const { return database_name_; } inline const common::ObString &get_reverse_cluster_name() const { return reverse_cluster_name_; } inline const common::ObString &get_reverse_tenant_name() const { return reverse_tenant_name_; } inline const common::ObString &get_reverse_user_name() const { return reverse_user_name_; } @@ -5051,6 +5053,8 @@ public: inline int64_t get_driver_proto() const { return driver_proto_; } inline void set_driver_proto(int64_t proto) { driver_proto_ = proto; } + inline bool get_if_not_exist() const { return if_not_exist_; } + inline void set_if_not_exist(bool value) { if_not_exist_ = value; } inline int64_t get_flag() const { return flag_; } inline void set_flag(int64_t flag) { flag_ = flag; } inline const common::ObString &get_service_name() const { return service_name_; } @@ -5061,8 +5065,9 @@ public: void reset(); virtual bool is_valid() const; - VIRTUAL_TO_STRING_KV(K_(tenant_id), K_(owner_id), K_(dblink_id), K_(dblink_name), - K_(cluster_name), K_(tenant_name), K_(user_name), K_(host_addr), + VIRTUAL_TO_STRING_KV(K_(tenant_id), K_(owner_id), K_(if_not_exist), K_(dblink_id), K_(dblink_name), + K_(cluster_name), K_(tenant_name), K_(database_name), K_(user_name), + K_(host_addr), K_(driver_proto), K_(flag), K_(service_name), K_(conn_string), K_(authusr), K_(authpwd), K_(passwordx), K_(authpwdx), K_(password), K_(encrypted_password), K_(plain_password), @@ -5100,6 +5105,8 @@ protected: common::ObString reverse_password_; // used for reverse dblink common::ObString plain_reverse_password_; // used for reverse dblink common::ObAddr reverse_host_addr_; // used for reverse dblink + common::ObString database_name_; // used for mysql dblink + bool if_not_exist_; // used for mysql dblink }; struct ObTenantDbLinkId @@ -5200,7 +5207,8 @@ public: + reverse_tenant_name_.length() + 1 + reverse_user_name_.length() + 1 + reverse_password_.length() + 1 - + plain_reverse_password_.length() + 1; + + plain_reverse_password_.length() + 1 + + database_name_.length() + 1; } }; diff --git a/src/share/schema/ob_user_sql_service.cpp b/src/share/schema/ob_user_sql_service.cpp index 9b9cdfe028..4ff25f1fb2 100644 --- a/src/share/schema/ob_user_sql_service.cpp +++ b/src/share/schema/ob_user_sql_service.cpp @@ -84,7 +84,7 @@ int ObUserSqlService::replace_user( int64_t affected_rows = 0; ObDMLExecHelper exec(sql_client, exec_tenant_id); ObDMLSqlSplicer dml; - if (OB_FAIL(gen_user_dml(exec_tenant_id, user, dml))) { + if (OB_FAIL(gen_user_dml(exec_tenant_id, user, dml, false))) { LOG_WARN("gen_user_dml failed", K(ret)); } @@ -98,7 +98,7 @@ int ObUserSqlService::replace_user( } // insert into __all_user_history - if (FAILEDx(add_user_history(user, new_schema_version, sql_client))) { + if (FAILEDx(add_user_history(user, new_schema_version, sql_client, false))) { LOG_WARN("add_user_history failed", K(user), K(new_schema_version), K(ret)); } @@ -368,7 +368,7 @@ int ObUserSqlService::rename_user( } // update __all_user history table - if (FAILEDx(add_user_history(user_info, new_schema_version, sql_client))) { + if (FAILEDx(add_user_history(user_info, new_schema_version, sql_client, false))) { LOG_WARN("add_user_history failed", K(user_info), K(new_schema_version), K(ret)); } @@ -462,7 +462,7 @@ int ObUserSqlService::set_passwd_impl( } // update __all_user history table - if (FAILEDx(add_user_history(user_info, new_schema_version, sql_client))) { + if (FAILEDx(add_user_history(user_info, new_schema_version, sql_client, false))) { LOG_WARN("add_user_history failed", K(user_info), K(new_schema_version), K(ret)); } @@ -521,7 +521,7 @@ int ObUserSqlService::set_max_connections( } // update __all_user history table - if (FAILEDx(add_user_history(user_info, new_schema_version, sql_client))) { + if (FAILEDx(add_user_history(user_info, new_schema_version, sql_client, false))) { LOG_WARN("add_user_history failed", K(user_info), K(new_schema_version), K(ret)); } @@ -582,7 +582,7 @@ int ObUserSqlService::alter_user_require( } // update __all_user history table - if (FAILEDx(add_user_history(user_info, new_schema_version, sql_client))) { + if (FAILEDx(add_user_history(user_info, new_schema_version, sql_client, false))) { LOG_WARN("add_user_history failed", K(user_info), K(new_schema_version), K(ret)); } @@ -607,7 +607,8 @@ int ObUserSqlService::grant_revoke_user( const ObUserInfo &user_info, const int64_t new_schema_version, const ObString *ddl_stmt_str, - ObISQLClient &sql_client) + ObISQLClient &sql_client, + const bool is_from_inner_sql) { int ret = OB_SUCCESS; const uint64_t tenant_id = user_info.get_tenant_id(); @@ -622,7 +623,7 @@ int ObUserSqlService::grant_revoke_user( int64_t affected_rows = 0; ObDMLExecHelper exec(sql_client, exec_tenant_id); ObDMLSqlSplicer dml; - if (OB_FAIL(gen_user_dml(exec_tenant_id, user_info, dml))) { + if (OB_FAIL(gen_user_dml(exec_tenant_id, user_info, dml, is_from_inner_sql))) { LOG_WARN("gen_user_dml failed", K(user_info), K(ret)); } @@ -635,7 +636,7 @@ int ObUserSqlService::grant_revoke_user( } // insert into __all_user_history - if (FAILEDx(add_user_history(user_info, new_schema_version, sql_client))) { + if (FAILEDx(add_user_history(user_info, new_schema_version, sql_client, is_from_inner_sql))) { LOG_WARN("add_user_history failed", K(user_info), K(new_schema_version), K(ret)); } @@ -694,7 +695,7 @@ int ObUserSqlService::alter_user_profile( } // update __all_user history table - if (FAILEDx(add_user_history(user_info, user_info.get_schema_version(), sql_client))) { + if (FAILEDx(add_user_history(user_info, user_info.get_schema_version(), sql_client, false))) { LOG_WARN("add_user_history failed", K(user_info), K(ret)); } @@ -753,7 +754,7 @@ int ObUserSqlService::lock_user( } // update __all_user history table - if (FAILEDx(add_user_history(user_info, new_schema_version, sql_client))) { + if (FAILEDx(add_user_history(user_info, new_schema_version, sql_client, false))) { LOG_WARN("add_user_history failed", K(user_info), K(new_schema_version), K(ret)); } @@ -777,7 +778,8 @@ int ObUserSqlService::lock_user( int ObUserSqlService::add_user_history( const ObUserInfo &user_info, const int64_t schema_version, - common::ObISQLClient &sql_client) + common::ObISQLClient &sql_client, + const bool is_from_inner_sql) { int ret = OB_SUCCESS; const uint64_t tenant_id = user_info.get_tenant_id(); @@ -785,7 +787,7 @@ int ObUserSqlService::add_user_history( ObDMLExecHelper exec(sql_client, exec_tenant_id); ObDMLSqlSplicer dml; int64_t affected_rows = 0; - if (OB_FAIL(gen_user_dml(exec_tenant_id, user_info, dml))) { + if (OB_FAIL(gen_user_dml(exec_tenant_id, user_info, dml, is_from_inner_sql))) { LOG_WARN("gen_user_dml failed", K(user_info), K(ret)); } else { const int64_t is_deleted = 0; @@ -805,12 +807,16 @@ int ObUserSqlService::add_user_history( int ObUserSqlService::gen_user_dml( const uint64_t exec_tenant_id, const ObUserInfo &user, - ObDMLSqlSplicer &dml) + ObDMLSqlSplicer &dml, + const bool is_from_inner_sql) { int ret = OB_SUCCESS; const bool is_ssl_support = (user.get_ssl_type() != ObSSLType::SSL_TYPE_NOT_SPECIFIED); - LOG_INFO("gen_user_dml", K(is_ssl_support), K(user)); - if (OB_FAIL(dml.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id( + LOG_INFO("gen_user_dml", K(is_ssl_support), K(user), K(is_from_inner_sql)); + uint64_t compat_version = 0; + if (OB_FAIL(GET_MIN_DATA_VERSION(user.get_tenant_id(), compat_version))) { + LOG_WARN("fail to get data version", KR(ret), K(user.get_tenant_id())); + } else if (OB_FAIL(dml.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id( exec_tenant_id, user.get_tenant_id()))) || OB_FAIL(dml.add_pk_column("user_id", ObSchemaUtils::get_extract_schema_id( exec_tenant_id,user.get_user_id()))) @@ -856,6 +862,16 @@ int ObUserSqlService::gen_user_dml( || OB_FAIL(dml.add_time_column("password_last_changed", user.get_password_last_changed())) || OB_FAIL(dml.add_gmt_modified())) { LOG_WARN("add column failed", K(ret)); + } else if (!is_from_inner_sql && compat_version < DATA_VERSION_4_2_0_0) { + if (1 == user.get_priv(OB_PRIV_DROP_DATABASE_LINK) || + 1 == user.get_priv(OB_PRIV_CREATE_DATABASE_LINK)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("some column of user info is not empty when MIN_DATA_VERSION is below DATA_VERSION_4_2_0_0", K(ret), K(user.get_priv(OB_PRIV_DROP_DATABASE_LINK)), K(user.get_priv(OB_PRIV_CREATE_DATABASE_LINK))); + } + } else if (OB_FAIL(dml.add_column("PRIV_DROP_DATABASE_LINK", user.get_priv(OB_PRIV_DROP_DATABASE_LINK) ? 1 : 0))) { + LOG_WARN("add PRIV_DROP_DATABASE_LINK column failed", K(user.get_priv(OB_PRIV_DROP_DATABASE_LINK)), K(ret)); + } else if (OB_FAIL(dml.add_column("PRIV_CREATE_DATABASE_LINK", user.get_priv(OB_PRIV_CREATE_DATABASE_LINK) ? 1 : 0))) { + LOG_WARN("add PRIV_CREATE_DATABASE_LINK column failed", K(user.get_priv(OB_PRIV_CREATE_DATABASE_LINK)), K(ret)); } return ret; } @@ -879,7 +895,7 @@ int ObUserSqlService::update_user_schema_version( const ObUserInfo &user_info = user_infos.at(i); if (OB_FAIL(schema_service_.gen_new_schema_version(tenant_id, OB_INVALID_VERSION, new_schema_version))) { LOG_WARN("fail to gen new schema_version", K(ret), K(tenant_id)); - } else if (OB_FAIL(add_user_history(user_info, new_schema_version, sql_client))) { + } else if (OB_FAIL(add_user_history(user_info, new_schema_version, sql_client, false))) { LOG_WARN("add_user_history failed", K(user_info), K(new_schema_version), K(ret)); } // log operation diff --git a/src/share/schema/ob_user_sql_service.h b/src/share/schema/ob_user_sql_service.h index 15e1833bba..65784a490f 100644 --- a/src/share/schema/ob_user_sql_service.h +++ b/src/share/schema/ob_user_sql_service.h @@ -81,7 +81,8 @@ public: virtual int grant_revoke_user(const ObUserInfo &user_info, const int64_t new_schema_version, const common::ObString *ddl_stmt_str, - common::ObISQLClient &sql_client); + common::ObISQLClient &sql_client, + const bool is_from_inner_sql); virtual int lock_user(const ObUserInfo &user_info, const int64_t new_schema_version, const common::ObString *ddl_stmt_str, @@ -95,11 +96,13 @@ public: common::ObISQLClient &sql_client); static int add_user_history(const ObUserInfo &user, const int64_t schema_version, - common::ObISQLClient &sql_client); + common::ObISQLClient &sql_client, + const bool is_from_inner_sql); static int gen_user_dml(const uint64_t exec_tenant_id, const ObUserInfo &user, - share::ObDMLSqlSplicer &dml); + share::ObDMLSqlSplicer &dml, + const bool is_from_inner_sql); virtual int replace_user( const ObUserInfo &user, const int64_t new_schema_version, diff --git a/src/sql/CMakeLists.txt b/src/sql/CMakeLists.txt index 64e800d7c6..527e192b21 100644 --- a/src/sql/CMakeLists.txt +++ b/src/sql/CMakeLists.txt @@ -366,6 +366,7 @@ ob_set_subtarget(ob_sql engine_expr engine/expr/ob_expr_json_contains_path.cpp engine/expr/ob_expr_json_depth.cpp engine/expr/ob_expr_json_keys.cpp + engine/expr/ob_expr_current_scn.cpp engine/expr/ob_expr_json_overlaps.cpp engine/expr/ob_expr_json_remove.cpp engine/expr/ob_expr_json_replace.cpp diff --git a/src/sql/code_generator/ob_tsc_cg_service.cpp b/src/sql/code_generator/ob_tsc_cg_service.cpp index ca8a10e709..c535ddae4c 100644 --- a/src/sql/code_generator/ob_tsc_cg_service.cpp +++ b/src/sql/code_generator/ob_tsc_cg_service.cpp @@ -78,6 +78,7 @@ int ObTscCgService::generate_tsc_ctdef(ObLogTableScan &op, ObTableScanCtDef &tsc } else { const ObExecContext *exec_ctx = nullptr; tsc_ctdef.flashback_item_.flashback_query_type_ = op.get_flashback_query_type(); + tsc_ctdef.flashback_item_.fq_read_tx_uncommitted_ = op.get_fq_read_tx_uncommitted(); if (OB_ISNULL(exec_ctx = cg_.opt_ctx_->get_exec_ctx())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(ret)); diff --git a/src/sql/das/ob_das_scan_op.cpp b/src/sql/das/ob_das_scan_op.cpp index 0bf2c16f13..f020260334 100644 --- a/src/sql/das/ob_das_scan_op.cpp +++ b/src/sql/das/ob_das_scan_op.cpp @@ -74,7 +74,8 @@ OB_DEF_SERIALIZE(ObDASScanRtDef) scan_flag_, pd_storage_flag_, need_check_output_datum_, - is_for_foreign_check_); + is_for_foreign_check_, + fb_read_tx_uncommitted_); return ret; } @@ -94,7 +95,8 @@ OB_DEF_DESERIALIZE(ObDASScanRtDef) scan_flag_, pd_storage_flag_, need_check_output_datum_, - is_for_foreign_check_); + is_for_foreign_check_, + fb_read_tx_uncommitted_); if (OB_SUCC(ret)) { (void)ObSQLUtils::adjust_time_by_ntp_offset(timeout_ts_); } @@ -117,7 +119,8 @@ OB_DEF_SERIALIZE_SIZE(ObDASScanRtDef) scan_flag_, pd_storage_flag_, need_check_output_datum_, - is_for_foreign_check_); + is_for_foreign_check_, + fb_read_tx_uncommitted_); return len; } @@ -238,7 +241,9 @@ int ObDASScanOp::init_scan_param() scan_param_.tenant_schema_version_ = scan_rtdef_->tenant_schema_version_; scan_param_.limit_param_ = scan_rtdef_->limit_param_; scan_param_.need_scn_ = scan_rtdef_->need_scn_; - scan_param_.pd_storage_flag_ = scan_ctdef_->pd_expr_spec_.pd_storage_flag_; scan_param_.fb_snapshot_ = scan_rtdef_->fb_snapshot_; + scan_param_.pd_storage_flag_ = scan_ctdef_->pd_expr_spec_.pd_storage_flag_; + scan_param_.fb_snapshot_ = scan_rtdef_->fb_snapshot_; + scan_param_.fb_read_tx_uncommitted_ = scan_rtdef_->fb_read_tx_uncommitted_; if (scan_rtdef_->is_for_foreign_check_) { scan_param_.trans_desc_ = trans_desc_; } @@ -1215,6 +1220,7 @@ OB_INLINE int ObLocalIndexLookupOp::init_scan_param() scan_param_.need_scn_ = lookup_rtdef_->need_scn_; scan_param_.pd_storage_flag_ = lookup_ctdef_->pd_expr_spec_.pd_storage_flag_; scan_param_.fb_snapshot_ = lookup_rtdef_->fb_snapshot_; + scan_param_.fb_read_tx_uncommitted_ = lookup_rtdef_->fb_read_tx_uncommitted_; scan_param_.ls_id_ = ls_id_; scan_param_.tablet_id_ = tablet_id_; if (lookup_rtdef_->is_for_foreign_check_) { diff --git a/src/sql/das/ob_das_scan_op.h b/src/sql/das/ob_das_scan_op.h index a2829126f1..dd9adc5890 100644 --- a/src/sql/das/ob_das_scan_op.h +++ b/src/sql/das/ob_das_scan_op.h @@ -109,6 +109,7 @@ public: need_scn_(false), force_refresh_lc_(false), need_check_output_datum_(false), + fb_read_tx_uncommitted_(false), frozen_version_(-1), fb_snapshot_(), timeout_ts_(-1), @@ -129,6 +130,7 @@ public: K_(force_refresh_lc), K_(frozen_version), K_(fb_snapshot), + K_(fb_read_tx_uncommitted), K_(timeout_ts), K_(tx_lock_timeout), K_(sql_mode), @@ -141,6 +143,7 @@ public: bool need_scn_; bool force_refresh_lc_; bool need_check_output_datum_; + bool fb_read_tx_uncommitted_; int64_t frozen_version_; share::SCN fb_snapshot_; int64_t timeout_ts_; diff --git a/src/sql/dblink/ob_dblink_utils.cpp b/src/sql/dblink/ob_dblink_utils.cpp index e9c9fe2e35..2f68dda197 100644 --- a/src/sql/dblink/ob_dblink_utils.cpp +++ b/src/sql/dblink/ob_dblink_utils.cpp @@ -84,6 +84,42 @@ int ObDblinkService::get_length_from_type_text(ObString &type_text, int32_t &len return ret; } +int ObDblinkService::get_set_sql_mode_cstr(sql::ObSQLSessionInfo *session_info, const char *&set_sql_mode_cstr, ObIAllocator &allocator) +{ + int ret = OB_SUCCESS; + ObSqlString set_sql_mode_sql; + ObObj sql_mode_int_obj; + ObObj sql_mode_str_obj; + const char *set_sql_mode_fmt = "SET SESSION sql_mode = '%.*s'"; + void *buf = NULL; + int64_t copy_len = 0; + if (lib::is_oracle_mode()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("only used in mysql mode", K(ret)); + } else if (OB_ISNULL(session_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null ptr", K(ret)); + } else if (OB_FAIL(session_info->get_sys_variable(share::SYS_VAR_SQL_MODE, sql_mode_int_obj))) { + LOG_WARN("failed to get SYS_VAR_SET_REVERSE_DBLINK_INFOS", K(sql_mode_int_obj), K(ret)); + } else if (OB_FAIL(ob_sql_mode_to_str(sql_mode_int_obj, sql_mode_str_obj, &allocator))) { + LOG_WARN("failed sql mode to str", K(sql_mode_int_obj), K(ret)); + } else if (OB_FAIL(set_sql_mode_sql.append_fmt(set_sql_mode_fmt, + sql_mode_str_obj.val_len_, + sql_mode_str_obj.v_.string_))) { + LOG_WARN("append sql failed", K(ret), K(sql_mode_str_obj)); + } else if (FALSE_IT([&]{ copy_len = set_sql_mode_sql.length(); }())) { + } else if (OB_ISNULL(buf = allocator.alloc(copy_len + 1))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("failed to allocate memory", K(ret), K(copy_len)); + } else { + MEMCPY(buf, set_sql_mode_sql.ptr(), copy_len); + char *sql_cstr = static_cast(buf); + sql_cstr[copy_len] = 0; + set_sql_mode_cstr = sql_cstr; + } + return ret; +} + ObReverseLink::ObReverseLink() : user_(), tenant_(), @@ -214,13 +250,10 @@ int ObReverseLink::open(int64_t session_sql_req_level) (void)snprintf(db_pass_, sizeof(db_pass_), "%.*s", passwd_.length(), passwd_.ptr()); LOG_DEBUG("open reverse link connection", K(ret), K(db_user_), K(db_pass_), K(addr_)); if (OB_FAIL(reverse_conn_.connect(db_user_, db_pass_, "", addr_, 10, true, session_sql_req_level))) { //just set connect timeout to 10s, read and write have not timeout - ObDblinkUtils::process_dblink_errno(common::sqlclient::DBLINK_DRV_OB, ret); LOG_WARN("failed to open reverse link connection", K(ret), K(db_user_), K(db_pass_), K(addr_)); } else if (OB_FAIL(reverse_conn_.set_timeout_variable(LONG_QUERY_TIMEOUT, common::sqlclient::ObMySQLConnectionPool::DEFAULT_TRANSACTION_TIMEOUT_US))) { - ObDblinkUtils::process_dblink_errno(common::sqlclient::DBLINK_DRV_OB, ret); LOG_WARN("failed to set reverse link connection's timeout", K(ret)); } else if (OB_FAIL(ObDbLinkProxy::execute_init_sql(&reverse_conn_, common::sqlclient::DBLINK_DRV_OB))) { - ObDblinkUtils::process_dblink_errno(common::sqlclient::DBLINK_DRV_OB, ret); LOG_WARN("failed to init reverse link connection", K(ret)); } else { is_close_ = false; @@ -241,8 +274,6 @@ int ObReverseLink::read(const char *sql, ObISQLClient::ReadResult &res) ret = OB_NOT_INIT; LOG_WARN("reverse link connection is closed", K(ret)); } else if (OB_FAIL(reverse_conn_.execute_read(OB_INVALID_TENANT_ID, sql, res))) { - int dblink_errno = ret; - ObDblinkUtils::process_dblink_errno(common::sqlclient::DblinkDriverProto::DBLINK_DRV_OB, &reverse_conn_, ret); LOG_WARN("faild to read by reverse link connection", K(ret), K(sql)); } else { LOG_DEBUG("succ to read by reverse link connection", K(ret), K(sql)); @@ -261,57 +292,6 @@ int ObReverseLink::close() return ret; } -int ObDblinkUtils::process_dblink_errno(common::sqlclient::DblinkDriverProto dblink_type, common::sqlclient::ObISQLConnection *dblink_conn, int &ob_errno) { - // The purpose of adding the process_dblink_errno function - // is to distinguish the errno processing when dblink connects to other types of databases. - const int orcl_errno = ob_errno; - switch (dblink_type) { - case common::sqlclient::DblinkDriverProto::DBLINK_DRV_OB: { - if (OB_UNLIKELY(NULL == dblink_conn)) { - get_ob_errno_from_oracle_errno(orcl_errno, NULL, ob_errno); - } else { - get_ob_errno_from_oracle_errno(orcl_errno, mysql_error(static_cast(dblink_conn)->get_handler()), ob_errno); - } - break; - } - case common::sqlclient::DblinkDriverProto::DBLINK_DRV_OCI: { - get_ob_errno_from_oracle_errno(orcl_errno, NULL, ob_errno); - } - default: { - //nothing - break; - } - } - // some oracle error code can not translate to oceanbase error code, - // so use OB_ERR_DBLINK_REMOTE_ECODE to represent those oracle error code. - if (orcl_errno == ob_errno && - // error code -40xx will report from code in deps/, need skip it - (ob_errno != -4016 || ob_errno != -4012 || - ob_errno != -4013 || ob_errno != -4002 || ob_errno != -4007)) { - LOG_USER_ERROR(OB_ERR_DBLINK_REMOTE_ECODE, orcl_errno); - ob_errno = OB_ERR_DBLINK_REMOTE_ECODE; - } - return OB_SUCCESS; -} - -int ObDblinkUtils::process_dblink_errno(common::sqlclient::DblinkDriverProto dblink_type, int &ob_errno) { - // The purpose of adding the process_dblink_errno function - // is to distinguish the errno processing when dblink connects to other types of databases. - const int orcl_errno = ob_errno; - get_ob_errno_from_oracle_errno(orcl_errno, NULL, ob_errno); - // some oracle error code can not translate to oceanbase error code, - // so use OB_ERR_DBLINK_REMOTE_ECODE to represent those oracle error code. - if (-4016 == ob_errno || - -4012 == ob_errno || - -4002 == ob_errno) { - // do nothing - } else if (orcl_errno == ob_errno) { - LOG_USER_ERROR(OB_ERR_DBLINK_REMOTE_ECODE, orcl_errno); - ob_errno = OB_ERR_DBLINK_REMOTE_ECODE; - } - return OB_SUCCESS; -} - int ObDblinkUtils::has_reverse_link_or_any_dblink(const ObDMLStmt *stmt, bool &has, bool has_any_dblink) { int ret = OB_SUCCESS; const common::ObIArray &table_items = stmt->get_table_items(); diff --git a/src/sql/dblink/ob_dblink_utils.h b/src/sql/dblink/ob_dblink_utils.h index 84715d12a6..18d408e806 100644 --- a/src/sql/dblink/ob_dblink_utils.h +++ b/src/sql/dblink/ob_dblink_utils.h @@ -32,6 +32,7 @@ class ObDblinkService public: static int check_lob_in_result(common::sqlclient::ObMySQLResult *result, bool &have_lob); static int get_length_from_type_text(ObString &type_text, int32_t &length); + static int get_set_sql_mode_cstr(sql::ObSQLSessionInfo *session_info, const char *&set_sql_mode_cstr, ObIAllocator &allocator); }; enum DblinkGetConnType { @@ -99,8 +100,6 @@ private: class ObDblinkUtils { public: - static int process_dblink_errno(common::sqlclient::DblinkDriverProto dblink_type, common::sqlclient::ObISQLConnection *dblink_conn, int &ob_errno); - static int process_dblink_errno(common::sqlclient::DblinkDriverProto dblink_type, int &ob_errno); static int has_reverse_link_or_any_dblink(const ObDMLStmt *stmt, bool &has, bool has_any_dblink = false); }; diff --git a/src/sql/engine/dml/ob_link_dml_op.cpp b/src/sql/engine/dml/ob_link_dml_op.cpp index 15c7df2a24..727012af35 100644 --- a/src/sql/engine/dml/ob_link_dml_op.cpp +++ b/src/sql/engine/dml/ob_link_dml_op.cpp @@ -112,7 +112,6 @@ int ObLinkDmlOp::inner_execute_link_stmt(const char *link_stmt) } else if (MY_SPEC.is_reverse_link_ && OB_FAIL(send_reverse_link_info(tx_id))) { LOG_WARN("failed to send reverse link info", K(ret), K(link_stmt)); } else if (OB_FAIL(dblink_proxy_->dblink_write(dblink_conn_, affected_rows_, link_stmt))) { - ObDblinkUtils::process_dblink_errno(link_type_, dblink_conn_, ret); LOG_WARN("write failed", K(ret), K(link_stmt)); } else { LOG_DEBUG("LINKDMLOP succ to dblink write", K(affected_rows_), K(link_stmt), KP(dblink_conn_), K(ret)); diff --git a/src/sql/engine/dml/ob_link_op.cpp b/src/sql/engine/dml/ob_link_op.cpp index a084c48a21..fc5f265f94 100644 --- a/src/sql/engine/dml/ob_link_op.cpp +++ b/src/sql/engine/dml/ob_link_op.cpp @@ -6,6 +6,7 @@ #include "share/schema/ob_dblink_mgr.h" #include "lib/mysqlclient/ob_mysql_connection.h" #include "lib/mysqlclient/ob_mysql_connection_pool.h" +#include "common/sql_mode/ob_sql_mode_utils.h" #include "sql/ob_sql_utils.h" namespace oceanbase { @@ -136,7 +137,7 @@ int ObLinkOp::init_dblink(uint64_t dblink_id, ObDbLinkProxy *dblink_proxy, bool dblink_schema_->get_tenant_name(), dblink_schema_->get_user_name(), dblink_schema_->get_plain_password(), - ObString(""), + dblink_schema_->get_database_name(), dblink_schema_->get_conn_string(), dblink_schema_->get_cluster_name(), param_ctx))) { @@ -145,17 +146,21 @@ int ObLinkOp::init_dblink(uint64_t dblink_id, ObDbLinkProxy *dblink_proxy, bool LOG_WARN("failed to get dblink connection from session", K(my_session), K(sessid_), K(ret)); } else { if (NULL == dblink_conn) { - if (OB_FAIL(dblink_proxy->acquire_dblink(dblink_id, - link_type_, - param_ctx, - dblink_conn_, - sessid_, - next_sql_req_level_))) { - ObDblinkUtils::process_dblink_errno(link_type_, dblink_conn_, ret); + const char *set_sql_mode_sql = NULL; + if (!is_oracle_mode() && OB_FAIL(ObDblinkService::get_set_sql_mode_cstr(my_session, set_sql_mode_sql, allocator_))) { + LOG_WARN("failed to get set_sql_mode_sql", K(ret)); + } else if (OB_FAIL(dblink_proxy->acquire_dblink(dblink_id, + link_type_, + param_ctx, + dblink_conn_, + sessid_, + next_sql_req_level_, + set_sql_mode_sql))) { LOG_WARN("failed to acquire dblink", K(ret), K(dblink_id)); } else if (OB_FAIL(my_session->get_dblink_context().register_dblink_conn_pool(dblink_conn_->get_common_server_pool()))) { LOG_WARN("failed to register dblink conn pool to current session", K(ret)); - } else if (in_xa_trascaction_ && OB_FAIL(my_session->get_dblink_context().set_dblink_conn(dblink_conn_))) { + } else if (in_xa_trascaction_ && lib::is_oracle_mode() && + OB_FAIL(my_session->get_dblink_context().set_dblink_conn(dblink_conn_))) { LOG_WARN("failed to set dblink connection to session", K(my_session), K(sessid_), K(ret)); } else { LOG_INFO("link op get connection from dblink pool", KP(dblink_conn_), K(lbt())); @@ -241,6 +246,7 @@ int ObLinkOp::combine_link_stmt(const ObString &link_stmt_fmt, obj_print_params.cs_type_ = ctx_.get_my_session()->get_nls_collation(); } obj_print_params.need_cast_expr_ = true; + obj_print_params.print_const_expr_type_ = true; while (OB_SUCC(ret) && link_stmt_pos == saved_stmt_pos) { //Previously, the format parameter of the print sql literal function was NULL. //In the procedure scenario, when dblink reverse spell trunc(date type), it will treat the date type as a string, diff --git a/src/sql/engine/expr/ob_expr_current_scn.cpp b/src/sql/engine/expr/ob_expr_current_scn.cpp new file mode 100644 index 0000000000..39bae292e9 --- /dev/null +++ b/src/sql/engine/expr/ob_expr_current_scn.cpp @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2021 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 SQL_ENG +#include "sql/engine/expr/ob_expr_current_scn.h" +#include "lib/ob_name_def.h" +#include "sql/session/ob_sql_session_info.h" +#include "sql/engine/ob_physical_plan_ctx.h" +#include "sql/engine/ob_exec_context.h" +#include "src/sql/engine/expr/ob_expr_util.h" + +namespace oceanbase +{ +using namespace common; +using namespace share; +using namespace transaction; +#include "src/storage/tx/ob_tx_api.h" +namespace sql +{ +ObExprCurrentScn::ObExprCurrentScn(ObIAllocator &alloc) + : ObFuncExprOperator(alloc, T_FUN_SYS_CURRENT_SCN, N_CURRENT_SCN, 0, NOT_VALID_FOR_GENERATED_COL, NOT_ROW_DIMENSION) +{ +} +ObExprCurrentScn::~ObExprCurrentScn() +{ +} + +int ObExprCurrentScn::calc_result_type0(ObExprResType &type, ObExprTypeCtx &type_ctx) const +{ + UNUSED(type_ctx); + if (is_oracle_mode()) { + const ObAccuracy &acc = ObAccuracy::DDL_DEFAULT_ACCURACY2[common::ORACLE_MODE][common::ObNumberType]; + type.set_number(); + type.set_scale(acc.get_scale()); + type.set_precision(acc.get_precision()); + } else { + const ObAccuracy &acc = common::ObAccuracy::DDL_DEFAULT_ACCURACY[common::ObUInt64Type]; + type.set_uint64(); + type.set_scale(acc.get_scale()); + type.set_precision(acc.get_precision()); + type.set_result_flag(NOT_NULL_FLAG); + } + return OB_SUCCESS; +} + +int ObExprCurrentScn::eval_current_scn(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum) +{ + int ret = OB_SUCCESS; + ObSQLSessionInfo *session = NULL; + if (OB_ISNULL(session = ctx.exec_ctx_.get_my_session())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("session is null", K(ret)); + } else { + share::SCN current_scn; + ObTransService *txs = MTL(transaction::ObTransService*); + int64_t query_timeout = 0; + session->get_query_timeout(query_timeout); + int64_t expire_ts = session->get_query_start_time() + query_timeout; + if (OB_FAIL(txs->get_read_snapshot_version(expire_ts, current_scn))) { + LOG_WARN("get read snapshot version", K(ret)); + } else if (ObUInt64Type == expr.datum_meta_.type_) { + expr_datum.set_uint(current_scn.get_val_for_sql()); + } else { + uint64_t scn_version = current_scn.get_val_for_sql(); + ObNumStackOnceAlloc tmp_alloc; + number::ObNumber num; + if (OB_FAIL(num.from(scn_version, tmp_alloc))) { + LOG_WARN("copy number fail", K(ret)); + } else { + expr_datum.set_number(num); + } + } + } + return ret; +} + +int ObExprCurrentScn::cg_expr(ObExprCGCtx &op_cg_ctx, const ObRawExpr &raw_expr, + ObExpr &rt_expr) const +{ + UNUSED(raw_expr); + UNUSED(op_cg_ctx); + rt_expr.eval_func_ = ObExprCurrentScn::eval_current_scn; + return OB_SUCCESS; +} + +} //namespace sql +} //namespace oceanbase diff --git a/src/sql/engine/expr/ob_expr_current_scn.h b/src/sql/engine/expr/ob_expr_current_scn.h new file mode 100644 index 0000000000..f427f7295f --- /dev/null +++ b/src/sql/engine/expr/ob_expr_current_scn.h @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2021 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_SQL_OB_EXPR_CURRENT_SCN_H_ +#define OCEANBASE_SQL_OB_EXPR_CURRENT_SCN_H_ + +#include "sql/engine/expr/ob_expr_operator.h" + +namespace oceanbase +{ +namespace sql +{ +class ObExprCurrentScn : public ObFuncExprOperator +{ +public: + explicit ObExprCurrentScn(common::ObIAllocator &alloc); + virtual ~ObExprCurrentScn(); + virtual int calc_result_type0(ObExprResType &type, common::ObExprTypeCtx &type_ctx) const; + static int eval_current_scn(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum); + virtual int cg_expr(ObExprCGCtx &op_cg_ctx, + const ObRawExpr &raw_expr, + ObExpr &rt_expr) const override; + +private: + // disallow copy + DISALLOW_COPY_AND_ASSIGN(ObExprCurrentScn); +}; + +} //sql +} //oceanbase +#endif //OCEANBASE_SQL_OB_EXPR_CURRENT_SCN_H_ diff --git a/src/sql/engine/expr/ob_expr_eval_functions.cpp b/src/sql/engine/expr/ob_expr_eval_functions.cpp index 82159828a7..6b5ab6bf09 100644 --- a/src/sql/engine/expr/ob_expr_eval_functions.cpp +++ b/src/sql/engine/expr/ob_expr_eval_functions.cpp @@ -310,6 +310,7 @@ #include "ob_expr_encrypt.h" #include "ob_expr_coalesce.h" #include "ob_expr_cast.h" +#include "ob_expr_current_scn.h" #include "ob_expr_icu_version.h" #include "ob_expr_sql_mode_convert.h" #include "ob_expr_priv_xml_binary.h" @@ -1030,7 +1031,8 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = { ObExprXmlcast::eval_xmlcast, /* 602 */ ObExprUpdateXml::eval_update_xml, /* 603 */ ObExprJoinFilter::eval_range_filter, /* 604 */ - ObExprJoinFilter::eval_in_filter /* 605 */ + ObExprJoinFilter::eval_in_filter, /* 605 */ + ObExprCurrentScn::eval_current_scn /* 606 */ }; static ObExpr::EvalBatchFunc g_expr_eval_batch_functions[] = { diff --git a/src/sql/engine/expr/ob_expr_operator_factory.cpp b/src/sql/engine/expr/ob_expr_operator_factory.cpp index b05a9f2f44..4c88ac5dff 100644 --- a/src/sql/engine/expr/ob_expr_operator_factory.cpp +++ b/src/sql/engine/expr/ob_expr_operator_factory.cpp @@ -382,6 +382,7 @@ #include "sql/engine/expr/ob_expr_st_contains.h" #include "sql/engine/expr/ob_expr_st_within.h" #include "sql/engine/expr/ob_expr_priv_st_asewkb.h" +#include "sql/engine/expr/ob_expr_current_scn.h" #include "sql/engine/expr/ob_expr_name_const.h" #include "sql/engine/expr/ob_expr_format_bytes.h" #include "sql/engine/expr/ob_expr_format_pico_time.h" @@ -984,6 +985,7 @@ void ObExprOperatorFactory::register_expr_operators() REG_OP(ObExprDesDecrypt); REG_OP(ObExprDesEncrypt); REG_OP(ObExprEncrypt); + REG_OP(ObExprCurrentScn); REG_OP(ObExprEncode); REG_OP(ObExprDecode); REG_OP(ObExprICUVersion); @@ -1282,6 +1284,7 @@ void ObExprOperatorFactory::register_expr_operators() REG_OP_ORCL(ObExprJsonExists); REG_OP_ORCL(ObExprJsonArray); REG_OP_ORCL(ObExprJsonObject); + REG_OP_ORCL(ObExprCurrentScn); REG_OP_ORCL(ObExprTreat); REG_OP_ORCL(ObExprGeneratorFunc); REG_OP_ORCL(ObExprZipf); diff --git a/src/sql/engine/ob_exec_context.cpp b/src/sql/engine/ob_exec_context.cpp index 2556912429..a428eef0dd 100644 --- a/src/sql/engine/ob_exec_context.cpp +++ b/src/sql/engine/ob_exec_context.cpp @@ -125,7 +125,8 @@ ObExecContext::ObExecContext(ObIAllocator &allocator) register_op_id_(OB_INVALID_ID), tmp_alloc_used_(false), table_direct_insert_ctx_(), - errcode_(OB_SUCCESS) + errcode_(OB_SUCCESS), + dblink_snapshot_map_() { } diff --git a/src/sql/engine/ob_exec_context.h b/src/sql/engine/ob_exec_context.h index b9d620cb2d..67c6085a7f 100644 --- a/src/sql/engine/ob_exec_context.h +++ b/src/sql/engine/ob_exec_context.h @@ -465,6 +465,7 @@ public: ObTableDirectInsertCtx &get_table_direct_insert_ctx() { return table_direct_insert_ctx_; } void set_errcode(const int errcode) { ATOMIC_STORE(&errcode_, errcode); } int get_errcode() const { return ATOMIC_LOAD(&errcode_); } + hash::ObHashMap &get_dblink_snapshot_map() { return dblink_snapshot_map_; } ObExecFeedbackInfo &get_feedback_info() { return fb_info_; }; private: int build_temp_expr_ctx(const ObTempExpr &temp_expr, ObTempExprCtx *&temp_expr_ctx); @@ -640,6 +641,7 @@ protected: ObTableDirectInsertCtx table_direct_insert_ctx_; // for deadlock detect, set in do_close_plan int errcode_; + hash::ObHashMap dblink_snapshot_map_; // for feedback ObExecFeedbackInfo fb_info_; //--------------- diff --git a/src/sql/engine/table/ob_link_scan_op.cpp b/src/sql/engine/table/ob_link_scan_op.cpp index 28a127fd87..406093d6aa 100644 --- a/src/sql/engine/table/ob_link_scan_op.cpp +++ b/src/sql/engine/table/ob_link_scan_op.cpp @@ -50,7 +50,8 @@ ObLinkScanOp::ObLinkScanOp(ObExecContext &exec_ctx, const ObOpSpec &spec, ObOpIn tm_session_(NULL), tm_rm_connection_(NULL), reverse_link_(NULL), - conn_type_(sql::DblinkGetConnType::DBLINK_POOL) + conn_type_(sql::DblinkGetConnType::DBLINK_POOL), + snapshot_created_(NULL) { } @@ -76,6 +77,7 @@ int ObLinkScanOp::init_tz_info(const ObTimeZoneInfo *tz_info) return ret; } + int ObLinkScanOp::inner_execute_link_stmt(const char *link_stmt) { int ret = OB_SUCCESS; @@ -86,12 +88,12 @@ int ObLinkScanOp::inner_execute_link_stmt(const char *link_stmt) transaction::ObTransID tx_id; bool have_lob = false; res_.set_enable_use_result(true); + bool new_snapshot = false; if (OB_ISNULL(link_stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected NULL", K(ret), KP(link_stmt)); } else if (sql::DblinkGetConnType::TM_CONN == conn_type_) { if (OB_FAIL(tm_rm_connection_->execute_read(OB_INVALID_TENANT_ID, link_stmt, res_))) { - ObDblinkUtils::process_dblink_errno(DblinkDriverProto(tm_rm_connection_->get_dblink_driver_proto()), ret); LOG_WARN("failed to read table data by tm_rm_connection", K(ret), K(link_stmt), K(DblinkDriverProto(tm_rm_connection_->get_dblink_driver_proto()))); } else { LOG_DEBUG("succ to read table data by tm_rm_connection", K(link_stmt), K(DblinkDriverProto(tm_rm_connection_->get_dblink_driver_proto()))); @@ -105,9 +107,10 @@ int ObLinkScanOp::inner_execute_link_stmt(const char *link_stmt) } else if (OB_ISNULL(dblink_proxy_) || OB_ISNULL(my_session)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected NULL", K(ret), KP(dblink_proxy_), KP(my_session)); - } else if (OB_FAIL(dblink_proxy_->dblink_read(dblink_conn_, res_, link_stmt))) { - ObDblinkUtils::process_dblink_errno(link_type_, dblink_conn_, ret); - LOG_WARN("read failed", K(ret), K(link_stmt)); + } else { + if (OB_FAIL(dblink_proxy_->dblink_read(dblink_conn_, res_, link_stmt))) { + LOG_WARN("read failed", K(ret), K(link_type_), K(dblink_conn_), K(link_stmt)); + } } if (OB_FAIL(ret)) { // do nothing diff --git a/src/sql/engine/table/ob_link_scan_op.h b/src/sql/engine/table/ob_link_scan_op.h index 4cf8dca347..bee32dcdb5 100644 --- a/src/sql/engine/table/ob_link_scan_op.h +++ b/src/sql/engine/table/ob_link_scan_op.h @@ -43,6 +43,8 @@ public: private: virtual void reset_dblink() override; void reset_result(); + int init_conn_snapshot(bool &new_snapshot); + int free_snapshot(); bool need_tx(const ObSQLSessionInfo *my_session) const; private: common::ObMySQLProxy::MySQLResult res_; @@ -55,6 +57,8 @@ private: common::sqlclient::ObISQLConnection *tm_rm_connection_; ObReverseLink *reverse_link_; sql::DblinkGetConnType conn_type_; + // snapshot created by this operator, need free it when close. + void *snapshot_created_; }; } // end namespace sql diff --git a/src/sql/engine/table/ob_table_scan_op.cpp b/src/sql/engine/table/ob_table_scan_op.cpp index 27f0e82ca1..060904248f 100644 --- a/src/sql/engine/table/ob_table_scan_op.cpp +++ b/src/sql/engine/table/ob_table_scan_op.cpp @@ -59,6 +59,7 @@ int FlashBackItem::set_flashback_query_info(ObEvalCtx &eval_ctx, ObDASScanRtDef ret = OB_ERR_UNEXPECTED; LOG_WARN("NULL value", K(ret)); } else { + scan_rtdef.fb_read_tx_uncommitted_ = fq_read_tx_uncommitted_; if (TableItem::USING_TIMESTAMP == flashback_query_type_) { if (ObTimestampTZType != expr->datum_meta_.type_) { ret = OB_ERR_UNEXPECTED; @@ -123,6 +124,7 @@ OB_DEF_SERIALIZE(ObTableScanCtDef) } OB_UNIS_ENCODE(calc_part_id_expr_); OB_UNIS_ENCODE(global_index_rowkey_exprs_); + OB_UNIS_ENCODE(flashback_item_.fq_read_tx_uncommitted_); return ret; } @@ -149,6 +151,7 @@ OB_DEF_SERIALIZE_SIZE(ObTableScanCtDef) } OB_UNIS_ADD_LEN(calc_part_id_expr_); OB_UNIS_ADD_LEN(global_index_rowkey_exprs_); + OB_UNIS_ADD_LEN(flashback_item_.fq_read_tx_uncommitted_); return len; } @@ -192,6 +195,7 @@ OB_DEF_DESERIALIZE(ObTableScanCtDef) } OB_UNIS_DECODE(calc_part_id_expr_); OB_UNIS_DECODE(global_index_rowkey_exprs_); + OB_UNIS_DECODE(flashback_item_.fq_read_tx_uncommitted_); return ret; } diff --git a/src/sql/engine/table/ob_table_scan_op.h b/src/sql/engine/table/ob_table_scan_op.h index c96e65a22c..7978df6dd4 100644 --- a/src/sql/engine/table/ob_table_scan_op.h +++ b/src/sql/engine/table/ob_table_scan_op.h @@ -46,15 +46,18 @@ public: FlashBackItem() : need_scn_(false), flashback_query_expr_(nullptr), - flashback_query_type_(TableItem::NOT_USING) + flashback_query_type_(TableItem::NOT_USING), + fq_read_tx_uncommitted_(false) { } int set_flashback_query_info(ObEvalCtx &eval_ctx, ObDASScanRtDef &scan_rtdef) const; TO_STRING_KV(K_(need_scn), KPC_(flashback_query_expr), - K_(flashback_query_type)); + K_(flashback_query_type), + K_(fq_read_tx_uncommitted)); bool need_scn_; ObExpr *flashback_query_expr_; //flashback query expr TableItem::FlashBackQueryType flashback_query_type_; //flashback query type + bool fq_read_tx_uncommitted_; // whether read uncommitted changes in transaction }; struct ObSpatialIndexCache diff --git a/src/sql/ob_dml_stmt_printer.cpp b/src/sql/ob_dml_stmt_printer.cpp index eec2974ead..d668d7b813 100644 --- a/src/sql/ob_dml_stmt_printer.cpp +++ b/src/sql/ob_dml_stmt_printer.cpp @@ -915,7 +915,16 @@ int ObDMLStmtPrinter::print_base_table(const TableItem *table_item) } // flashback query if (OB_SUCC(ret)) { - if (OB_NOT_NULL(table_item->flashback_query_expr_)) { + bool explain_non_extend = false; + if (OB_NOT_NULL(stmt_->get_query_ctx()) && + OB_NOT_NULL(stmt_->get_query_ctx()->root_stmt_) && + stmt_->get_query_ctx()->root_stmt_->is_explain_stmt()) { + explain_non_extend = !static_cast + (stmt_->get_query_ctx()->root_stmt_)->is_explain_extended(); + } + if (OB_NOT_NULL(table_item->flashback_query_expr_) && + // do not print flashback of link table when explain [basic] + !(table_item->is_link_table() && explain_non_extend)) { if (table_item->flashback_query_type_ == TableItem::USING_TIMESTAMP) { DATA_PRINTF(" as of timestamp "); if (OB_FAIL(expr_printer_.do_print(table_item->flashback_query_expr_, T_NONE_SCOPE))) { @@ -1200,23 +1209,67 @@ int ObDMLStmtPrinter::print_limit() } else if (stmt_->has_fetch() || is_oracle_mode()) { /*有fetch,说明是oracle mode下的fetch填充的limit,这里不应该打印 */ } else { - if (NULL != stmt_->get_offset_expr() || NULL != stmt_->get_limit_expr()) { + ObRawExpr *offset_expr = stmt_->get_offset_expr(); + ObRawExpr *limit_expr = stmt_->get_limit_expr(); + if (NULL != offset_expr || NULL != limit_expr) { DATA_PRINTF(" limit "); } // offset if (OB_SUCC(ret)) { - if (NULL != stmt_->get_offset_expr()) { - if (OB_FAIL(expr_printer_.do_print(stmt_->get_offset_expr(), T_NONE_SCOPE))) { - LOG_WARN("fail to print order offset expr", K(ret)); + if (NULL != offset_expr) { + if (NULL != print_params_.exec_ctx_) { + ObArenaAllocator allocator("PrintDMLStmt"); + ObObj result; + bool got_result = false; + if (!offset_expr->is_static_const_expr()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("offset expr should be a const int", K(ret), KPC(offset_expr)); + } else if (OB_FAIL(ObSQLUtils::calc_const_or_calculable_expr(print_params_.exec_ctx_, + offset_expr, + result, + got_result, + allocator))) { + LOG_WARN("failed to calc offset expr", K(ret)); + } else if (!got_result || !result.is_int()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to get the result of offset expr", K(ret), KPC(offset_expr)); + } else { + DATA_PRINTF("%ld", result.get_int()); + } + } else { + if (OB_FAIL(expr_printer_.do_print(offset_expr, T_NONE_SCOPE))) { + LOG_WARN("fail to print offset expr", K(ret)); + } } DATA_PRINTF(","); } } // limit if (OB_SUCC(ret)) { - if (NULL != stmt_->get_limit_expr()) { - if (OB_FAIL(expr_printer_.do_print(stmt_->get_limit_expr(), T_NONE_SCOPE))) { - LOG_WARN("fail to print order limit expr", K(ret)); + if (NULL != limit_expr) { + if (NULL != print_params_.exec_ctx_) { + ObArenaAllocator allocator("PrintDMLStmt"); + ObObj result; + bool got_result = false; + if (!limit_expr->is_static_const_expr()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("limit expr should be a const int", K(ret), KPC(limit_expr)); + } else if (OB_FAIL(ObSQLUtils::calc_const_or_calculable_expr(print_params_.exec_ctx_, + limit_expr, + result, + got_result, + allocator))) { + LOG_WARN("failed to calc limit expr", K(ret)); + } else if (!got_result || !result.is_int()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to get the result of limit expr", K(ret), KPC(limit_expr)); + } else { + DATA_PRINTF("%ld", result.get_int()); + } + } else { + if (OB_FAIL(expr_printer_.do_print(limit_expr, T_NONE_SCOPE))) { + LOG_WARN("fail to print limit expr", K(ret)); + } } } } diff --git a/src/sql/ob_sql.cpp b/src/sql/ob_sql.cpp index 68f43df37c..270065202e 100644 --- a/src/sql/ob_sql.cpp +++ b/src/sql/ob_sql.cpp @@ -2911,6 +2911,7 @@ int ObSql::generate_plan(ParseResult &parse_result, ObDMLStmt *stmt = static_cast(basic_stmt); SQL_LOG(DEBUG, "stmt", "stmt", *stmt); SQL_LOG(DEBUG, "stmt success", "query", SJ(*stmt)); + stmt->get_query_ctx()->root_stmt_ = stmt; const ObGlobalHint &global_hint = stmt->get_query_ctx()->get_global_hint(); sql_ctx.session_info_->set_early_lock_release(global_hint.enable_lock_early_release_); ObOptimizerContext optctx(sql_ctx.session_info_, diff --git a/src/sql/ob_sql_context.cpp b/src/sql/ob_sql_context.cpp index bcaec580fd..fff8eded25 100644 --- a/src/sql/ob_sql_context.cpp +++ b/src/sql/ob_sql_context.cpp @@ -19,6 +19,7 @@ #include "sql/optimizer/ob_log_plan.h" #include "share/schema/ob_schema_getter_guard.h" #include "sql/dblink/ob_dblink_utils.h" +#include "src/storage/tx/ob_trans_define_v4.h" using namespace ::oceanbase::common; namespace oceanbase @@ -323,6 +324,7 @@ void ObSqlSchemaGuard::reset() schema_guard_ = NULL; allocator_.reset(); next_link_table_id_ = 1; + dblink_scn_.reuse(); } TableItem *ObSqlSchemaGuard::get_table_item_by_ref_id(const ObDMLStmt *stmt, uint64_t ref_table_id) @@ -411,13 +413,41 @@ int ObSqlSchemaGuard::get_table_schema(uint64_t dblink_id, if (OB_SUCC(ret) && OB_ISNULL(table_schema)) { ObTableSchema *tmp_schema = NULL; OV (OB_NOT_NULL(schema_guard_), OB_NOT_INIT); + uint64_t current_scn = OB_INVALID_ID; + uint64_t *scn = NULL; + if (OB_SUCC(ret)) { + if (OB_ISNULL(session_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("session info is null", K(ret)); + } else { + bool use_scn = (session_info->is_in_transaction() && + transaction::ObTxIsolationLevel::RC == session_info->get_tx_desc()->get_isolation_level()) + || !session_info->is_in_transaction(); + if (use_scn && OB_FAIL(get_link_current_scn(dblink_id, tenant_id, session_info, current_scn))) { + if (OB_HASH_NOT_EXIST == ret) { + scn = ¤t_scn; + ret = OB_SUCCESS; + } else { + LOG_WARN("get link current scn failed", K(ret)); + } + } + } + } OZ (schema_guard_->get_link_table_schema(tenant_id, dblink_id, database_name, table_name, allocator_, tmp_schema, session_info, dblink_name, - is_reverse_link)); + is_reverse_link, + scn)); + if (OB_SUCC(ret) && (NULL != scn)) { + if (OB_FAIL(dblink_scn_.set_refactored(dblink_id, *scn))) { + LOG_WARN("set refactored failed", K(ret)); + } else { + LOG_TRACE("set dblink current scn", K(dblink_id), K(*scn)); + } + } OV (OB_NOT_NULL(tmp_schema)); OX (tmp_schema->set_table_id(next_link_table_id_++)); OX (tmp_schema->set_link_table_id(tmp_schema->get_table_id())); @@ -587,6 +617,28 @@ int ObSqlSchemaGuard::get_link_column_schema(uint64_t table_id, uint64_t column_ return ret; } +int ObSqlSchemaGuard::get_link_current_scn(uint64_t dblink_id, uint64_t tenant_id, + ObSQLSessionInfo *session_info, + uint64_t ¤t_scn) +{ + int ret = OB_SUCCESS; + current_scn = OB_INVALID_ID; + if (!dblink_scn_.created()) { + if (OB_FAIL(dblink_scn_.create(4, "DblinkScnMap", "DblinkScnMap", tenant_id))) { + LOG_WARN("create hash map failed", K(ret)); + } else { + ret = OB_HASH_NOT_EXIST; + } + } else { + if (OB_FAIL(dblink_scn_.get_refactored(dblink_id, current_scn))) { + if (OB_HASH_NOT_EXIST != ret) { + LOG_WARN("get dblink scn failed", K(ret)); + } + } + } + return ret; +} + int ObSqlCtx::set_partition_infos(const ObTablePartitionInfoArray &info, ObIAllocator &allocator) { int ret = OB_SUCCESS; diff --git a/src/sql/ob_sql_context.h b/src/sql/ob_sql_context.h index 1400cb3409..83174dc494 100644 --- a/src/sql/ob_sql_context.h +++ b/src/sql/ob_sql_context.h @@ -24,6 +24,7 @@ #include "sql/plan_cache/ob_plan_cache_util.h" #include "observer/omt/ob_tenant_config_mgr.h" #include "share/client_feedback/ob_feedback_partition_struct.h" +#include "sql/dblink/ob_dblink_utils.h" namespace oceanbase { @@ -374,6 +375,11 @@ public: const share::schema::ObColumnSchemaV2 *&column_schema) const; int get_link_column_schema(uint64_t table_id, uint64_t column_id, const share::schema::ObColumnSchemaV2 *&column_schema) const; + int fetch_link_current_scn(uint64_t dblink_id, uint64_t tenant_id, ObSQLSessionInfo *session_info, + uint64_t ¤t_scn); + // get current scn from dblink. return OB_INVALID_ID if remote server not support current_scn + int get_link_current_scn(uint64_t dblink_id, uint64_t tenant_id, ObSQLSessionInfo *session_info, + uint64_t ¤t_scn); public: static TableItem *get_table_item_by_ref_id(const ObDMLStmt *stmt, uint64_t ref_table_id); static bool is_link_table(const ObDMLStmt *stmt, uint64_t table_id); @@ -382,6 +388,8 @@ private: common::ObArenaAllocator allocator_; common::ObSEArray table_schemas_; uint64_t next_link_table_id_; + // key is dblink_id, value is current scn. + common::hash::ObHashMap dblink_scn_; }; struct ObBaselineKey @@ -564,7 +572,8 @@ public: has_nested_sql_(false), tz_info_(NULL), res_map_rule_id_(common::OB_INVALID_ID), - res_map_rule_param_idx_(common::OB_INVALID_INDEX) + res_map_rule_param_idx_(common::OB_INVALID_INDEX), + root_stmt_(NULL) { } TO_STRING_KV(N_PARAM_NUM, question_marks_count_, @@ -603,6 +612,7 @@ public: tz_info_ = NULL; res_map_rule_id_ = common::OB_INVALID_ID; res_map_rule_param_idx_ = common::OB_INVALID_INDEX; + root_stmt_ = NULL; } int64_t get_new_stmt_id() { return stmt_count_++; } @@ -630,6 +640,7 @@ public: void set_has_nested_sql(bool has_nested_sql) { has_nested_sql_ = has_nested_sql; } void set_timezone_info(const common::ObTimeZoneInfo *tz_info) { tz_info_ = tz_info; } const common::ObTimeZoneInfo *get_timezone_info() const { return tz_info_; } + public: static const int64_t CALCULABLE_EXPR_NUM = 1; typedef common::ObSEArray CalculableItems; @@ -676,6 +687,7 @@ public: const common::ObTimeZoneInfo *tz_info_; uint64_t res_map_rule_id_; int64_t res_map_rule_param_idx_; + ObDMLStmt *root_stmt_; }; } /* ns sql*/ } /* ns oceanbase */ diff --git a/src/sql/optimizer/ob_del_upd_log_plan.cpp b/src/sql/optimizer/ob_del_upd_log_plan.cpp index a890b5be01..30cba06912 100644 --- a/src/sql/optimizer/ob_del_upd_log_plan.cpp +++ b/src/sql/optimizer/ob_del_upd_log_plan.cpp @@ -181,7 +181,10 @@ int ObDelUpdLogPlan::generate_dblink_raw_plan() int ret = OB_SUCCESS; const ObDelUpdStmt *stmt = get_stmt(); ObLogicalOperator *top = NULL; - if (OB_ISNULL(stmt)) { + if (!lib::is_oracle_mode()) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("mysql dblink not support dml", K(ret)); + } else if (OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null ptr", K(ret)); } else if (OB_FAIL(allocate_link_dml_as_top(top))) { diff --git a/src/sql/optimizer/ob_log_link.cpp b/src/sql/optimizer/ob_log_link.cpp index 65846ea2db..e9d742aa4e 100644 --- a/src/sql/optimizer/ob_log_link.cpp +++ b/src/sql/optimizer/ob_log_link.cpp @@ -206,6 +206,7 @@ int ObLogLink::set_link_stmt(const ObDMLStmt* stmt) ObString sql; ObObjPrintParams print_param; print_param.for_dblink_ = 1; + // only link scan need print flashback query for dblink table ObOptimizerContext *opt_ctx = NULL; ObQueryCtx *query_ctx = NULL; ObSQLSessionInfo *session = NULL; @@ -213,7 +214,8 @@ int ObLogLink::set_link_stmt(const ObDMLStmt* stmt) int64_t hint_query_timeout_us = 0; if (OB_ISNULL(stmt) || OB_ISNULL(plan) || OB_ISNULL(opt_ctx = &get_plan()->get_optimizer_context()) || - OB_ISNULL(session = opt_ctx->get_session_info())) { + OB_ISNULL(session = opt_ctx->get_session_info()) || + OB_ISNULL(print_param.exec_ctx_ = opt_ctx->get_exec_ctx())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", KP(opt_ctx), KP(stmt), KP(session), KP(plan), K(ret)); } else if (NULL == (query_ctx = stmt->get_query_ctx())) { @@ -225,6 +227,7 @@ int ObLogLink::set_link_stmt(const ObDMLStmt* stmt) } else if (-1 == hint_query_timeout_us && FALSE_IT(query_ctx->get_query_hint_for_update().get_global_hint().merge_query_timeout_hint(session_query_timeout_us))) { // do nothing + } else if (FALSE_IT(query_ctx->get_query_hint_for_update().get_global_hint().set_flashback_read_tx_uncommitted(true))) { } else if (OB_FAIL(mark_exec_params(const_cast(stmt)))) { LOG_WARN("failed to mark exec params", K(ret)); } else if (OB_FAIL(ObSQLUtils::reconstruct_sql(plan->get_allocator(), stmt, sql, opt_ctx->get_schema_guard(), print_param))) { @@ -237,6 +240,7 @@ int ObLogLink::set_link_stmt(const ObDMLStmt* stmt) if (-1 == hint_query_timeout_us) { // restore query_timeout_hint query_ctx->get_query_hint_for_update().get_global_hint().reset_query_timeout_hint(); } + query_ctx->get_query_hint_for_update().get_global_hint().set_flashback_read_tx_uncommitted(false); return ret; } diff --git a/src/sql/optimizer/ob_log_link.h b/src/sql/optimizer/ob_log_link.h index 1465a5e066..d2282bfd2c 100644 --- a/src/sql/optimizer/ob_log_link.h +++ b/src/sql/optimizer/ob_log_link.h @@ -52,6 +52,7 @@ protected: ObSqlPlanItem &plan_item) override; private: int print_link_stmt(char *buf, int64_t buf_len); + virtual bool print_flashback_query() const { return false; }; protected: common::ObIAllocator &allocator_; char *stmt_fmt_buf_; diff --git a/src/sql/optimizer/ob_log_link_dml.h b/src/sql/optimizer/ob_log_link_dml.h index c4b54df1e5..6433354259 100644 --- a/src/sql/optimizer/ob_log_link_dml.h +++ b/src/sql/optimizer/ob_log_link_dml.h @@ -18,6 +18,8 @@ public: virtual int get_explain_name_internal(char *buf, const int64_t buf_len, int64_t &pos) override; virtual int get_plan_item_info(PlanText &plan_text, ObSqlPlanItem &plan_item) override; inline void set_dml_type(stmt::StmtType type) { dml_type_ = type; } +private: + virtual bool print_flashback_query() const override { return false; }; private: stmt::StmtType dml_type_; }; diff --git a/src/sql/optimizer/ob_log_link_scan.h b/src/sql/optimizer/ob_log_link_scan.h index 8f5187b6aa..b033a1a3a7 100644 --- a/src/sql/optimizer/ob_log_link_scan.h +++ b/src/sql/optimizer/ob_log_link_scan.h @@ -21,6 +21,9 @@ public: ObLogLinkScan(ObLogPlan &plan); virtual ~ObLogLinkScan() {} virtual int allocate_expr_post(ObAllocExprContext &ctx) override; +private: + virtual bool print_flashback_query() const override { return true; }; + }; } // namespace sql diff --git a/src/sql/optimizer/ob_log_plan.cpp b/src/sql/optimizer/ob_log_plan.cpp index 046576b9b7..5ce7e6afb3 100644 --- a/src/sql/optimizer/ob_log_plan.cpp +++ b/src/sql/optimizer/ob_log_plan.cpp @@ -4163,6 +4163,7 @@ int ObLogPlan::allocate_access_path(AccessPath *ap, scan->set_est_cost_info(&ap->get_cost_table_scan_info()); scan->set_flashback_query_expr(table_item->flashback_query_expr_); scan->set_flashback_query_type(table_item->flashback_query_type_); + scan->set_fq_read_tx_uncommitted(get_optimizer_context().get_global_hint().get_flashback_read_tx_uncommitted()); scan->set_table_id(ap->get_table_id()); scan->set_ref_table_id(ap->get_ref_table_id()); scan->set_index_table_id(ap->get_index_table_id()); diff --git a/src/sql/optimizer/ob_log_table_scan.h b/src/sql/optimizer/ob_log_table_scan.h index 9da7a619ef..285210c72c 100644 --- a/src/sql/optimizer/ob_log_table_scan.h +++ b/src/sql/optimizer/ob_log_table_scan.h @@ -69,6 +69,7 @@ public: diverse_path_count_(0), fq_expr_(NULL), fq_type_(TableItem::NOT_USING), + fq_read_tx_uncommitted_(false), bf_info_(), group_id_expr_(nullptr), use_batch_(false), @@ -404,6 +405,8 @@ public: inline int64_t get_diverse_path_count() const { return diverse_path_count_; } inline TableItem::FlashBackQueryType get_flashback_query_type() const {return fq_type_; } inline void set_flashback_query_type(TableItem::FlashBackQueryType type) { fq_type_ = type; } + inline bool get_fq_read_tx_uncommitted() const { return fq_read_tx_uncommitted_; } + inline void set_fq_read_tx_uncommitted(bool v) { fq_read_tx_uncommitted_ = v; } inline const ObRawExpr* get_flashback_query_expr() const { return fq_expr_; } inline ObRawExpr* &get_flashback_query_expr() { return fq_expr_; } inline void set_flashback_query_expr(ObRawExpr *expr) { fq_expr_ = expr; } @@ -557,6 +560,7 @@ protected: // memeber variables ObRawExpr* fq_expr_; //flashback query expr TableItem::FlashBackQueryType fq_type_; //flashback query type + bool fq_read_tx_uncommitted_; // whether flashback query read uncommitted changes in transaction ObPxBFStaticInfo bf_info_; // for join partition filter // end for partition join filter diff --git a/src/sql/optimizer/ob_select_log_plan.cpp b/src/sql/optimizer/ob_select_log_plan.cpp index beb6457786..c5f42d6f81 100644 --- a/src/sql/optimizer/ob_select_log_plan.cpp +++ b/src/sql/optimizer/ob_select_log_plan.cpp @@ -6502,6 +6502,7 @@ int ObSelectLogPlan::generate_late_materialization_table_get(ObLogTableScan *ind table_scan->set_location_type(index_scan->get_location_type()); table_scan->set_flashback_query_expr(index_scan->get_flashback_query_expr()); table_scan->set_flashback_query_type(index_scan->get_flashback_query_type()); + table_scan->set_fq_read_tx_uncommitted(index_scan->get_fq_read_tx_uncommitted()); table_scan->set_part_ids(index_scan->get_part_ids()); table_scan->get_table_name() = table_item->alias_name_.length() > 0 ? table_item->alias_name_ : table_item->table_name_; diff --git a/src/sql/parser/non_reserved_keywords_mysql_mode.c b/src/sql/parser/non_reserved_keywords_mysql_mode.c index 0dae101008..9094808453 100644 --- a/src/sql/parser/non_reserved_keywords_mysql_mode.c +++ b/src/sql/parser/non_reserved_keywords_mysql_mode.c @@ -151,6 +151,7 @@ static const NonReservedKeyword Mysql_none_reserved_keywords[] = {"context", CONTEXT}, {"contributors", CONTRIBUTORS}, {"continue", CONTINUE}, + {"connect", CONNECT}, {"convert", CONVERT}, {"copy", COPY}, {"count", COUNT}, @@ -413,6 +414,7 @@ static const NonReservedKeyword Mysql_none_reserved_keywords[] = {"left", LEFT}, {"less", LESS}, {"level", LEVEL}, + {"link", LINK}, {"lib", LIB}, {"like", LIKE}, {"limit", LIMIT}, @@ -519,6 +521,7 @@ static const NonReservedKeyword Mysql_none_reserved_keywords[] = {"multipolygon", MULTIPOLYGON}, {"mutex", MUTEX}, {"mysql_errno", MYSQL_ERRNO}, + {"my_name", MY_NAME}, {"name", NAME}, {"names", NAMES}, {"namespace", NAMESPACE}, diff --git a/src/sql/parser/sql_parser_mysql_mode.l b/src/sql/parser/sql_parser_mysql_mode.l index 34f20bbf64..af4244e703 100755 --- a/src/sql/parser/sql_parser_mysql_mode.l +++ b/src/sql/parser/sql_parser_mysql_mode.l @@ -993,6 +993,7 @@ Timestamp{whitespace}?\"[^\"]*\" { OPTIMIZER_FEATURES_ENABLE { return OPTIMIZER_FEATURES_ENABLE; } NO_QUERY_TRANSFORMATION { return NO_QUERY_TRANSFORMATION; } NO_COST_BASED_QUERY_TRANSFORMATION { return NO_COST_BASED_QUERY_TRANSFORMATION; } +FLASHBACK_READ_TX_UNCOMMITTED { return FLASHBACK_READ_TX_UNCOMMITTED; } TRANS_PARAM { return TRANS_PARAM; } PQ_DISTRIBUTE { return PQ_DISTRIBUTE; } PQ_DISTRIBUTE_WINDOW { return PQ_DISTRIBUTE_WINDOW; } diff --git a/src/sql/parser/sql_parser_mysql_mode.y b/src/sql/parser/sql_parser_mysql_mode.y index 8e64e67807..eeac507953 100755 --- a/src/sql/parser/sql_parser_mysql_mode.y +++ b/src/sql/parser/sql_parser_mysql_mode.y @@ -126,7 +126,7 @@ extern void obsql_oracle_parse_fatal_error(int32_t errcode, yyscan_t yyscanner, %nonassoc LOWER_PARENS //%nonassoc STRING_VALUE %left '(' ')' -%nonassoc SQL_CACHE SQL_NO_CACHE /*for shift/reduce conflict between opt_query_expresion_option_list and SQL_CACHE*/ +%nonassoc SQL_CACHE SQL_NO_CACHE CHARSET DATABASE_ID REPLICA_NUM/*for shift/reduce conflict between opt_query_expresion_option_list and SQL_CACHE*/ %nonassoc HIGHER_PARENS TRANSACTION SIZE AUTO SKEWONLY /*for simple_expr conflict*/ %left '.' %right NOT NOT2 @@ -184,7 +184,7 @@ USE_DISTRIBUTED_DML NO_USE_DISTRIBUTED_DML // direct load data hint DIRECT // hint related to optimizer statistics -APPEND NO_GATHER_OPTIMIZER_STATISTICS GATHER_OPTIMIZER_STATISTICS DBMS_STATS +APPEND NO_GATHER_OPTIMIZER_STATISTICS GATHER_OPTIMIZER_STATISTICS DBMS_STATS FLASHBACK_READ_TX_UNCOMMITTED // optimizer dynamic sampling hint DYNAMIC_SAMPLING // other @@ -259,7 +259,7 @@ END_P SET_VAR DELIMITER CODE COLLATION COLUMN_FORMAT COLUMN_NAME COLUMNS COMMENT COMMIT COMMITTED COMPACT COMPLETION COMPRESSED COMPRESSION COMPUTE CONCURRENT CONDENSED CONNECTION CONSISTENT CONSISTENT_MODE CONSTRAINT_CATALOG CONSTRAINT_NAME CONSTRAINT_SCHEMA CONTAINS CONTEXT CONTRIBUTORS COPY COUNT CPU CREATE_TIMESTAMP - CTXCAT CTX_ID CUBE CURDATE CURRENT STACKED CURTIME CURSOR_NAME CUME_DIST CYCLE CALC_PARTITION_ID + CTXCAT CTX_ID CUBE CURDATE CURRENT STACKED CURTIME CURSOR_NAME CUME_DIST CYCLE CALC_PARTITION_ID CONNECT DAG DATA DATAFILE DATA_TABLE_ID DATE DATE_ADD DATE_SUB DATETIME DAY DEALLOCATE DECRYPTION DEFAULT_AUTH DEFINER DELAY DELAY_KEY_WRITE DEPTH DES_KEY_FILE DENSE_RANK DESCRIPTION DESTINATION DIAGNOSTICS @@ -289,7 +289,8 @@ END_P SET_VAR DELIMITER LAG LANGUAGE LAST LAST_VALUE LEAD LEADER LEAVES LESS LEAK LEAK_MOD LEAK_RATE LIB LINESTRING LIST_ LISTAGG LOCAL LOCALITY LOCATION LOCKED LOCKS LOGFILE LOGONLY_REPLICA_NUM LOGS LOCK_ LOGICAL_READS - LEVEL LN LOG LS LOG_RESTORE_SOURCE LINE_DELIMITER + + LEVEL LN LOG LS LINK LOG_RESTORE_SOURCE LINE_DELIMITER MAJOR MANUAL MASTER MASTER_AUTO_POSITION MASTER_CONNECT_RETRY MASTER_DELAY MASTER_HEARTBEAT_PERIOD MASTER_HOST MASTER_LOG_FILE MASTER_LOG_POS MASTER_PASSWORD MASTER_PORT MASTER_RETRY_COUNT @@ -299,7 +300,7 @@ END_P SET_VAR DELIMITER MAX_UPDATES_PER_HOUR MAX_USER_CONNECTIONS MEDIUM MEMORY MEMTABLE MESSAGE_TEXT META MICROSECOND MIGRATE MIN MIN_CPU MIN_IOPS MINOR MIN_ROWS MINUS MINUTE MODE MODIFY MONTH MOVE MULTILINESTRING MULTIPOINT MULTIPOLYGON MUTEX MYSQL_ERRNO MIGRATION MAX_USED_PART_ID MAXIMIZE - MATERIALIZED MEMBER MEMSTORE_PERCENT MINVALUE + MATERIALIZED MEMBER MEMSTORE_PERCENT MINVALUE MY_NAME NAME NAMES NAMESPACE NATIONAL NCHAR NDB NDBCLUSTER NEW NEXT NO NOAUDIT NODEGROUP NONE NORMAL NOW NOWAIT NOMINVALUE NOMAXVALUE NOORDER NOCYCLE NOCACHE NO_WAIT NULLS NUMBER NVARCHAR NTILE NTH_VALUE NOARCHIVELOG NETWORK NOPARALLEL @@ -367,6 +368,7 @@ END_P SET_VAR DELIMITER %type create_restore_point_stmt drop_restore_point_stmt %type create_resource_stmt drop_resource_stmt alter_resource_stmt %type cur_timestamp_func cur_time_func cur_date_func now_synonyms_func utc_timestamp_func utc_time_func utc_date_func sys_interval_func sysdate_func +%type create_dblink_stmt drop_dblink_stmt dblink tenant opt_cluster opt_dblink %type opt_create_resource_pool_option_list create_resource_pool_option alter_resource_pool_option_list alter_resource_pool_option %type opt_shrink_unit_option id_list opt_shrink_tenant_unit_option %type opt_resource_unit_option_list resource_unit_option @@ -633,6 +635,8 @@ stmt: | purge_stmt { $$ = $1; check_question_mark($$, result); } | analyze_stmt { $$ = $1; check_question_mark($$, result); } | load_data_stmt { $$ = $1; check_question_mark($$, result); } + | create_dblink_stmt { $$ = $1; check_question_mark($$, result); } + | drop_dblink_stmt { $$ = $1; check_question_mark($$, result); } | create_sequence_stmt { $$ = $1; check_question_mark($$, result); } | alter_sequence_stmt { $$ = $1; check_question_mark($$, result); } | drop_sequence_stmt { $$ = $1; check_question_mark($$, result); } @@ -3894,13 +3898,37 @@ DROP RESTORE POINT relation_name *****************************************************************************/ create_database_stmt: -create_with_opt_hint database_key opt_if_not_exists database_factor opt_database_option_list +create_with_opt_hint DATABASE database_factor opt_database_option_list { (void)($1); - (void)($2); ParseNode *database_option = NULL; - merge_nodes(database_option, result, T_DATABASE_OPTION_LIST, $5); - malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_DATABASE, 3, $3, $4, database_option); + merge_nodes(database_option, result, T_DATABASE_OPTION_LIST, $4); + malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_DATABASE, 3, NULL, $3, database_option); +} +| create_with_opt_hint SCHEMA database_factor opt_database_option_list +{ + (void)($1); + ParseNode *database_option = NULL; + merge_nodes(database_option, result, T_DATABASE_OPTION_LIST, $4); + malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_DATABASE, 3, NULL, $3, database_option); +} +| create_with_opt_hint DATABASE IF not EXISTS database_factor opt_database_option_list +{ + (void)($1); + (void)($4); + ParseNode *database_option = NULL; + merge_nodes(database_option, result, T_DATABASE_OPTION_LIST, $7); + malloc_terminal_node($$, result->malloc_pool_, T_IF_NOT_EXISTS); + malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_DATABASE, 3, $$, $6, database_option); +} +| create_with_opt_hint SCHEMA IF not EXISTS database_factor opt_database_option_list +{ + (void)($1); + (void)($4); + ParseNode *database_option = NULL; + merge_nodes(database_option, result, T_DATABASE_OPTION_LIST, $7); + malloc_terminal_node($$, result->malloc_pool_, T_IF_NOT_EXISTS); + malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_DATABASE, 3, $$, $6, database_option); } ; @@ -4026,10 +4054,23 @@ READ WRITE { malloc_terminal_node($$, result->malloc_pool_, T_OFF); } * *****************************************************************************/ drop_database_stmt: -DROP database_key opt_if_exists database_factor +DROP DATABASE database_factor { - (void)($2); - malloc_non_terminal_node($$, result->malloc_pool_, T_DROP_DATABASE, 2, $3, $4); + malloc_non_terminal_node($$, result->malloc_pool_, T_DROP_DATABASE, 2, NULL, $3); +} +| DROP SCHEMA database_factor +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_DROP_DATABASE, 2, NULL, $3); +} +| DROP DATABASE IF EXISTS database_factor +{ + malloc_terminal_node($$, result->malloc_pool_, T_IF_EXISTS); + malloc_non_terminal_node($$, result->malloc_pool_, T_DROP_DATABASE, 2, $$, $5); +} +| DROP SCHEMA IF EXISTS database_factor +{ + malloc_terminal_node($$, result->malloc_pool_, T_IF_EXISTS); + malloc_non_terminal_node($$, result->malloc_pool_, T_DROP_DATABASE, 2, $$, $5); } ; @@ -8713,6 +8754,10 @@ READ_CONSISTENCY '(' consistency_level ')' { malloc_terminal_node($$, result->malloc_pool_, T_DBMS_STATS); } +| FLASHBACK_READ_TX_UNCOMMITTED +{ + malloc_terminal_node($$, result->malloc_pool_, T_FLASHBACK_READ_TX_UNCOMMITTED); +} ; transform_hint: @@ -10462,14 +10507,14 @@ opt_with_star: ; normal_relation_factor: -relation_name +relation_name opt_dblink { - malloc_non_terminal_node($$, result->malloc_pool_, T_RELATION_FACTOR, 2, NULL, $1); + malloc_non_terminal_node($$, result->malloc_pool_, T_RELATION_FACTOR, 3, NULL, $1, $2); dup_node_string($1, $$, result->malloc_pool_); } -| relation_name '.' relation_name +| relation_name '.' relation_name opt_dblink { - malloc_non_terminal_node($$, result->malloc_pool_, T_RELATION_FACTOR, 2, $1, $3); + malloc_non_terminal_node($$, result->malloc_pool_, T_RELATION_FACTOR, 3, $1, $3, $4); dup_node_string($3, $$, result->malloc_pool_); } | relation_name '.' mysql_reserved_keyword @@ -10496,6 +10541,15 @@ dot_relation_factor: } ; +opt_dblink: +USER_VARIABLE /* USER_VARIABLE is '@xxxx', see sql_parser.l */ +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_DBLINK_NAME, 2, $1, NULL); +} +| +{ $$ = NULL; } +; + relation_factor_in_hint: normal_relation_factor qb_name_option { @@ -12578,7 +12632,69 @@ ALTER SEQUENCE relation_factor opt_sequence_option_list } ; +/***************************************************************************** + * + * create / drop database link grammer + * + ******************************************************************************/ +create_dblink_stmt: +create_with_opt_hint DATABASE LINK dblink CONNECT TO user tenant DATABASE database_factor IDENTIFIED BY password ip_port opt_cluster +{ + (void)($1); + malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_DBLINK, 10, + NULL, /* opt_if_not_exists */ + $4, /* dblink name */ + $7, /* user name */ + $8, /* tenant name */ + $10, /* database name */ + $13, /* password */ + NULL, /* driver */ + $14, /* host ip port*/ + $15, /* optional cluster */ + NULL /* optional self credential */); +} +| create_with_opt_hint DATABASE LINK IF not EXISTS dblink CONNECT TO user tenant DATABASE database_factor IDENTIFIED BY password ip_port opt_cluster +{ + (void)($1); + (void)($5); + malloc_terminal_node($$, result->malloc_pool_, T_IF_NOT_EXISTS); + malloc_non_terminal_node($$, result->malloc_pool_, T_CREATE_DBLINK, 10, + $$, /* opt_if_not_exists */ + $7, /* dblink name */ + $10, /* user name */ + $11, /* tenant name */ + $13, /* database name */ + $16, /* password */ + NULL, /* driver */ + $17, /* host ip port*/ + $18, /* optional cluster */ + NULL /* optional self credential */); +} +; +drop_dblink_stmt: +DROP DATABASE LINK opt_if_exists dblink +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_DROP_DBLINK, 2, $4, $5); +} +; + +dblink: +relation_name +{ $$ = $1; } +; + +tenant: +USER_VARIABLE /* USER_VARIABLE is '@xxxx', see sql_parser.l */ +{ $$ = $1; } +; + +opt_cluster: +CLUSTER STRING_VALUE +{ $$ = $2; } +| +{ $$ = NULL; } +; /***************************************************************************** @@ -12909,7 +13025,16 @@ ALTER malloc_terminal_node($$, result->malloc_pool_, T_PRIV_TYPE); $$->value_ = OB_PRIV_REPL_CLIENT; } - +| DROP DATABASE LINK +{ + malloc_terminal_node($$, result->malloc_pool_, T_PRIV_TYPE); + $$->value_ = OB_PRIV_DROP_DATABASE_LINK; +} +| CREATE DATABASE LINK +{ + malloc_terminal_node($$, result->malloc_pool_, T_PRIV_TYPE); + $$->value_ = OB_PRIV_CREATE_DATABASE_LINK; +} ; @@ -15482,6 +15607,11 @@ SERVER opt_equal_mark STRING_VALUE (void)($2); malloc_non_terminal_node($$, result->malloc_pool_, T_IP_PORT, 1, $3); } +| +HOST STRING_VALUE +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_IP_PORT, 1, $2); +} ; zone_desc : @@ -17751,6 +17881,9 @@ ACCOUNT | BACKED | NAMESPACE | LIB +| LINK %prec LOWER_PARENS +| MY_NAME +| CONNECT | STATEMENT_ID ; diff --git a/src/sql/privilege_check/ob_privilege_check.cpp b/src/sql/privilege_check/ob_privilege_check.cpp index 2ba3c912e3..8be7b01520 100644 --- a/src/sql/privilege_check/ob_privilege_check.cpp +++ b/src/sql/privilege_check/ob_privilege_check.cpp @@ -1227,6 +1227,50 @@ int get_create_synonym_priv( return ret; } +int get_create_dblink_priv( + const ObSessionPrivInfo &session_priv, + const ObStmt *basic_stmt, + ObIArray &need_privs) +{ + int ret = OB_SUCCESS; + UNUSED(session_priv); + ObNeedPriv need_priv; + if (OB_ISNULL(basic_stmt)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("Basic stmt should be not be NULL", K(ret)); + } else if (stmt::T_CREATE_DBLINK != basic_stmt->get_stmt_type()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected stmt type", K(basic_stmt->get_stmt_type()), K(ret)); + } else { + need_priv.priv_set_ = OB_PRIV_CREATE_DATABASE_LINK; + need_priv.priv_level_ = OB_PRIV_USER_LEVEL; + ADD_NEED_PRIV(need_priv); + } + return ret; +} + +int get_drop_dblink_priv( + const ObSessionPrivInfo &session_priv, + const ObStmt *basic_stmt, + ObIArray &need_privs) +{ + int ret = OB_SUCCESS; + UNUSED(session_priv); + ObNeedPriv need_priv; + if (OB_ISNULL(basic_stmt)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("Basic stmt should be not be NULL", K(ret)); + } else if (stmt::T_DROP_DBLINK != basic_stmt->get_stmt_type()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected stmt type", K(basic_stmt->get_stmt_type()), K(ret)); + } else { + need_priv.priv_set_ = OB_PRIV_DROP_DATABASE_LINK; + need_priv.priv_level_ = OB_PRIV_USER_LEVEL; + ADD_NEED_PRIV(need_priv); + } + return ret; +} + int get_drop_synonym_priv( const ObSessionPrivInfo &session_priv, const ObStmt *basic_stmt, diff --git a/src/sql/resolver/ddl/ob_create_dblink_resolver.cpp b/src/sql/resolver/ddl/ob_create_dblink_resolver.cpp index 48edcb8489..a26b5c5f7a 100644 --- a/src/sql/resolver/ddl/ob_create_dblink_resolver.cpp +++ b/src/sql/resolver/ddl/ob_create_dblink_resolver.cpp @@ -58,6 +58,24 @@ int ObCreateDbLinkResolver::resolve(const ParseNode &parse_tree) create_dblink_stmt->set_user_id(session_info_->get_user_id()); LOG_TRACE("debug dblink create", K(session_info_->get_database_id())); } + if (!lib::is_oracle_mode() && OB_SUCC(ret)) { + uint64_t compat_version = 0; + uint64_t tenant_id = session_info_->get_effective_tenant_id(); + if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { + LOG_WARN("fail to get data version", KR(ret), K(tenant_id)); + } else if (compat_version < DATA_VERSION_4_2_0_0) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("mysql dblink is not supported when MIN_DATA_VERSION is below DATA_VERSION_4_2_0_0", K(ret)); + } else if (NULL != node->children_[IF_NOT_EXIST]) { + if (T_IF_NOT_EXISTS != node->children_[IF_NOT_EXIST]->type_) { + ret = OB_INVALID_ARGUMENT; + SQL_RESV_LOG(WARN, "invalid argument.", + K(ret), K(node->children_[1]->type_)); + } else { + create_dblink_stmt->set_if_not_exist(true); + } + } + } if (OB_SUCC(ret)) { ObString dblink_name; ParseNode *name_node = node->children_[DBLINK_NAME]; @@ -95,6 +113,18 @@ int ObCreateDbLinkResolver::resolve(const ParseNode &parse_tree) LOG_WARN("set tenant name failed", K(ret)); } } + if (!lib::is_oracle_mode() && OB_SUCC(ret)) { + ObString database_name; + ParseNode *name_node = node->children_[DATABASE_NAME]; + if (OB_ISNULL(name_node)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid parse tree", K(ret)); + } else if (FALSE_IT(database_name.assign_ptr(name_node->str_value_, static_cast(name_node->str_len_)))) { + // do nothing + } else if (OB_FAIL(create_dblink_stmt->set_database_name(database_name))) { + LOG_WARN("set database name failed", K(ret)); + } + } if (OB_SUCC(ret)) { ObString user_name; ParseNode *name_node = node->children_[USER_NAME]; @@ -158,7 +188,7 @@ int ObCreateDbLinkResolver::resolve(const ParseNode &parse_tree) } if (OB_FAIL(ret)) { //do nothing - } else if (OB_FAIL(resolve_opt_reverse_link(node, create_dblink_stmt, drv_type))) { + } else if (lib::is_oracle_mode() && OB_FAIL(resolve_opt_reverse_link(node, create_dblink_stmt, drv_type))) { LOG_WARN("failed to resolve optional reverse link", K(ret)); } else if (ObSchemaChecker::is_ora_priv_check()) { OZ (schema_checker_->check_ora_ddl_priv( diff --git a/src/sql/resolver/ddl/ob_create_dblink_resolver.h b/src/sql/resolver/ddl/ob_create_dblink_resolver.h index e4dbcd7561..518ed64839 100644 --- a/src/sql/resolver/ddl/ob_create_dblink_resolver.h +++ b/src/sql/resolver/ddl/ob_create_dblink_resolver.h @@ -21,15 +21,17 @@ namespace sql class ObCreateDbLinkStmt; class ObCreateDbLinkResolver: public ObDDLResolver { - static const int64_t DBLINK_NAME = 0; - static const int64_t USER_NAME = 1; - static const int64_t TENANT_NAME = 2; - static const int64_t PASSWORD = 3; - static const int64_t OPT_DRIVER = 4; - static const int64_t IP_PORT = 5; - static const int64_t OPT_CLUSTER = 6; - static const int64_t OPT_REVERSE_LINK = 7; - static const int64_t DBLINK_NODE_COUNT = 8; + static const int64_t IF_NOT_EXIST = 0; + static const int64_t DBLINK_NAME = 1; + static const int64_t USER_NAME = 2; + static const int64_t TENANT_NAME = 3; + static const int64_t DATABASE_NAME = 4; + static const int64_t PASSWORD = 5; + static const int64_t OPT_DRIVER = 6; + static const int64_t IP_PORT = 7; + static const int64_t OPT_CLUSTER =8; + static const int64_t OPT_REVERSE_LINK = 9; + static const int64_t DBLINK_NODE_COUNT = 10; static const int64_t REVERSE_LINK_USER_NAME = 0; static const int64_t REVERSE_LINK_TENANT_NAME = 1; diff --git a/src/sql/resolver/ddl/ob_create_dblink_stmt.h b/src/sql/resolver/ddl/ob_create_dblink_stmt.h index 29427520b2..0d10aa74cf 100644 --- a/src/sql/resolver/ddl/ob_create_dblink_stmt.h +++ b/src/sql/resolver/ddl/ob_create_dblink_stmt.h @@ -29,12 +29,14 @@ public: inline void set_tenant_id(const uint64_t id) { create_dblink_arg_.dblink_info_.set_tenant_id(id); } inline void set_user_id(const uint64_t id) { create_dblink_arg_.dblink_info_.set_owner_id(id); } inline int set_dblink_name(const common::ObString &name) { return create_dblink_arg_.dblink_info_.set_dblink_name(name); } + inline void set_if_not_exist(const bool if_not_exist) { return create_dblink_arg_.dblink_info_.set_if_not_exist(if_not_exist); } inline int set_cluster_name(const common::ObString &name) { return create_dblink_arg_.dblink_info_.set_cluster_name(name); } inline int set_tenant_name(const common::ObString &name) { return create_dblink_arg_.dblink_info_.set_tenant_name(name); } inline int set_user_name(const common::ObString &name) { return create_dblink_arg_.dblink_info_.set_user_name(name); } int set_password(const common::ObString &pwd); inline void set_reverse_host_addr(const common::ObAddr &addr) { create_dblink_arg_.dblink_info_.set_reverse_host_addr(addr); } inline int set_reverse_cluster_name(const common::ObString &name) { return create_dblink_arg_.dblink_info_.set_reverse_cluster_name(name); } + inline int set_database_name(const common::ObString &name) { return create_dblink_arg_.dblink_info_.set_database_name(name); } inline int set_reverse_tenant_name(const common::ObString &name) { return create_dblink_arg_.dblink_info_.set_reverse_tenant_name(name); } inline int set_reverse_user_name(const common::ObString &name) { return create_dblink_arg_.dblink_info_.set_reverse_user_name(name); } int set_reverse_password(const common::ObString &pwd); diff --git a/src/sql/resolver/ddl/ob_create_table_resolver.cpp b/src/sql/resolver/ddl/ob_create_table_resolver.cpp index 0bd131b89f..351089c832 100644 --- a/src/sql/resolver/ddl/ob_create_table_resolver.cpp +++ b/src/sql/resolver/ddl/ob_create_table_resolver.cpp @@ -449,6 +449,7 @@ int ObCreateTableResolver::resolve(const ParseNode &parse_tree) { int ret = OB_SUCCESS; bool is_temporary_table = false; + bool has_dblink_node = false; const bool is_mysql_mode = !is_oracle_mode(); ParseNode *create_table_node = const_cast(&parse_tree); CHECK_COMPATIBILITY_MODE(session_info_); @@ -528,9 +529,9 @@ int ObCreateTableResolver::resolve(const ParseNode &parse_tree) ret = OB_NOT_INIT; SQL_RESV_LOG(WARN, "session_info is null.", K(ret)); } else if (OB_FAIL(resolve_table_relation_node(create_table_node->children_[2], table_name, database_name, - false, false, &dblink_name_ptr, &dblink_name_len))) { + false, false, &dblink_name_ptr, &dblink_name_len, &has_dblink_node))) { SQL_RESV_LOG(WARN, "failed to resolve table relation node!", K(ret)); - } else if (NULL != dblink_name_ptr) { //don't care about dblink_name_len + } else if (has_dblink_node) { //don't care about dblink_name_len // Check whether the child nodes of table_node have dblink ParseNode, // If so, an error will be reported. ret = OB_ERR_DDL_ON_REMOTE_DATABASE; diff --git a/src/sql/resolver/ddl/ob_create_view_resolver.cpp b/src/sql/resolver/ddl/ob_create_view_resolver.cpp index b41637448c..dbcb0fc279 100644 --- a/src/sql/resolver/ddl/ob_create_view_resolver.cpp +++ b/src/sql/resolver/ddl/ob_create_view_resolver.cpp @@ -92,11 +92,12 @@ int ObCreateViewResolver::resolve(const ParseNode &parse_tree) ObNameCaseMode mode = OB_NAME_CASE_INVALID; bool perserve_lettercase = false; // lib::is_oracle_mode() ? true : (mode != OB_LOWERCASE_AND_INSENSITIVE); ObArray column_list; + bool has_dblink_node = false; if (OB_FAIL(resolve_table_relation_node(parse_tree.children_[VIEW_NODE], view_name, db_name, - false, false, &dblink_name_ptr, &dblink_name_len))) { + false, false, &dblink_name_ptr, &dblink_name_len, &has_dblink_node))) { LOG_WARN("failed to resolve table relation node!", K(ret)); - } else if (NULL != dblink_name_ptr) { //don't care about dblink_name_len + } else if (has_dblink_node) { //don't care about dblink_name_len ret = OB_ERR_MISSING_KEYWORD; LOG_WARN("missing keyword when create view", K(ret)); LOG_USER_ERROR(OB_ERR_MISSING_KEYWORD); diff --git a/src/sql/resolver/ddl/ob_drop_dblink_resolver.cpp b/src/sql/resolver/ddl/ob_drop_dblink_resolver.cpp index c297989544..566aba210e 100644 --- a/src/sql/resolver/ddl/ob_drop_dblink_resolver.cpp +++ b/src/sql/resolver/ddl/ob_drop_dblink_resolver.cpp @@ -55,6 +55,24 @@ int ObDropDbLinkResolver::resolve(const ParseNode &parse_tree) } else { stmt_ = drop_dblink_stmt; drop_dblink_stmt->set_tenant_id(session_info_->get_effective_tenant_id()); + } + if (!lib::is_oracle_mode() && OB_SUCC(ret)) { + uint64_t compat_version = 0; + uint64_t tenant_id = session_info_->get_effective_tenant_id(); + if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { + LOG_WARN("fail to get data version", KR(ret), K(tenant_id)); + } else if (compat_version < DATA_VERSION_4_2_0_0) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("mysql dblink is not supported when MIN_DATA_VERSION is below DATA_VERSION_4_2_0_0", K(ret)); + } else if (NULL != node->children_[IF_EXIST]) { + if (T_IF_EXISTS != node->children_[IF_EXIST]->type_) { + ret = OB_INVALID_ARGUMENT; + SQL_RESV_LOG(WARN, "invalid argument.", + K(ret), K(node->children_[1]->type_)); + } else { + drop_dblink_stmt->set_if_exist(true); + } + } } if (OB_SUCC(ret)) { ObString dblink_name; diff --git a/src/sql/resolver/ddl/ob_drop_dblink_resolver.h b/src/sql/resolver/ddl/ob_drop_dblink_resolver.h index eb8ae48fe7..cf666749b2 100644 --- a/src/sql/resolver/ddl/ob_drop_dblink_resolver.h +++ b/src/sql/resolver/ddl/ob_drop_dblink_resolver.h @@ -20,8 +20,9 @@ namespace sql { class ObDropDbLinkResolver: public ObDDLResolver { - static const int64_t DBLINK_NAME = 0; - static const int64_t DBLINK_NODE_COUNT = 1; + static const int64_t IF_EXIST = 0; + static const int64_t DBLINK_NAME = 1; + static const int64_t DBLINK_NODE_COUNT = 2; public: explicit ObDropDbLinkResolver(ObResolverParams ¶ms); virtual ~ObDropDbLinkResolver(); diff --git a/src/sql/resolver/ddl/ob_drop_dblink_stmt.h b/src/sql/resolver/ddl/ob_drop_dblink_stmt.h index cd7d07d689..dc5c38987a 100644 --- a/src/sql/resolver/ddl/ob_drop_dblink_stmt.h +++ b/src/sql/resolver/ddl/ob_drop_dblink_stmt.h @@ -28,7 +28,8 @@ public: inline void set_tenant_id(const uint64_t id) { drop_dblink_arg_.tenant_id_ =id; } inline void set_dblink_name(const common::ObString &name) { drop_dblink_arg_.dblink_name_ = name; } - + inline bool get_if_exist() { return drop_dblink_arg_.if_exist_; } + inline void set_if_exist(bool value) { drop_dblink_arg_.if_exist_ = true; } obrpc::ObDropDbLinkArg &get_drop_dblink_arg() { return drop_dblink_arg_; } virtual obrpc::ObDDLArg &get_ddl_arg() { return drop_dblink_arg_; } virtual bool cause_implicit_commit() const { return true; } diff --git a/src/sql/resolver/ddl/ob_drop_table_resolver.cpp b/src/sql/resolver/ddl/ob_drop_table_resolver.cpp index 37727e2fc8..f4e30ffad1 100644 --- a/src/sql/resolver/ddl/ob_drop_table_resolver.cpp +++ b/src/sql/resolver/ddl/ob_drop_table_resolver.cpp @@ -135,7 +135,7 @@ int ObDropTableResolver::resolve(const ParseNode &parse_tree) if (NULL == table_node) { ret = OB_ERR_UNEXPECTED; SQL_RESV_LOG(WARN, "table_node is null", K(ret)); - } else if (OB_FAIL(resolve_dblink_name(table_node, dblink_name, has_reverse_link, has_dblink_node))) { + } else if (OB_FAIL(resolve_dblink_name(table_node, session_info_->get_effective_tenant_id(), dblink_name, has_reverse_link, has_dblink_node))) { SQL_RESV_LOG(WARN, "failed to resolv dblink name", K(ret)); } else if (has_dblink_node) { if (has_reverse_link || !dblink_name.empty()) { diff --git a/src/sql/resolver/ddl/ob_explain_stmt.h b/src/sql/resolver/ddl/ob_explain_stmt.h index 3c2440b482..c74f25776a 100644 --- a/src/sql/resolver/ddl/ob_explain_stmt.h +++ b/src/sql/resolver/ddl/ob_explain_stmt.h @@ -52,6 +52,8 @@ public: const common::ObString& get_statement_id() const { return statement_id_; } void set_statement_id(const common::ObString& statement_id) { statement_id_ = statement_id; } virtual bool is_affect_found_rows() const { return is_select_explain(); } + bool is_explain_extended() const { return EXPLAIN_EXTENDED == format_ + || EXPLAIN_EXTENDED_NOADDR == format_; } DECLARE_VIRTUAL_TO_STRING; private: diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index 6a2d234afe..b1956e1a9b 100755 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -3511,6 +3511,7 @@ int ObDMLResolver::resolve_flashback_query_node(const ParseNode *time_node, Tabl tmp_time_node = time_node->children_[0]; if (OB_NOT_NULL(tmp_time_node)) { ObRawExpr *expr = nullptr; + ObQueryCtx *query_ctx = NULL; if (OB_FAIL(resolve_sql_expr(*tmp_time_node, expr))) { LOG_WARN("resolve sql expr failed", K(ret)); } else if (OB_ISNULL(expr)) { @@ -7802,7 +7803,7 @@ int ObDMLResolver::resolve_table_relation_factor(const ParseNode *node, if (OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session info is NULL", K(ret)); - } else if (OB_FAIL(resolve_dblink_name(node, dblink_name, is_reverse_link, has_dblink_node))) { + } else if (OB_FAIL(resolve_dblink_name(node, tenant_id, dblink_name, is_reverse_link, has_dblink_node))) { LOG_WARN("resolve dblink name failed", K(ret)); } else { LOG_DEBUG("resolve dblink name", K(dblink_name), K(is_reverse_link)); @@ -8011,57 +8012,49 @@ int ObDMLResolver::resolve_table_relation_factor_dblink(const ParseNode *table_n bool is_reverse_link) { int ret = OB_SUCCESS; - // db name node may null - ParseNode *dbname_node = table_node->children_[0]; - if (is_reverse_link) { - dblink_id = 0; //set reverse link's dblink id to 0 + ParseNode *dbname_node = table_node->children_[0]; // db name node maybe null, maybe not + const ObDbLinkSchema *dblink_schema = NULL; + ObString tmp_dbname; + if (OB_NOT_NULL(dbname_node)) { + int32_t database_name_len = static_cast(dbname_node->str_len_); + tmp_dbname.assign_ptr(dbname_node->str_value_, database_name_len); } if (OB_ISNULL(table_node) || OB_ISNULL(table_node->children_) || OB_ISNULL(table_node->children_[1])) { ret = OB_INVALID_ARGUMENT; LOG_WARN("table node or children is NULL", K(ret)); - } else if (!is_reverse_link && OB_FAIL(schema_checker_->get_dblink_id(tenant_id, dblink_name, dblink_id))) { - LOG_WARN("failed to get dblink info", K(ret), K(dblink_name)); - } else if (OB_INVALID_ID == dblink_id) { + } else if (is_reverse_link) { + dblink_id = 0; //set reverse link's dblink id to 0 + database_name = tmp_dbname; + } else if (OB_FAIL(schema_checker_->get_dblink_schema(tenant_id, dblink_name, dblink_schema))) { + LOG_WARN("failed to get dblink schema", K(ret)); + } else if (OB_ISNULL(dblink_schema)) { ret = OB_DBLINK_NOT_EXIST_TO_ACCESS; - LOG_WARN("dblink not exist", K(ret), K(tenant_id), K(dblink_name)); - } else { - if (OB_ISNULL(allocator_)) { - ret = OB_ERR_NULL_VALUE; - LOG_WARN("allocator is null", K(ret)); - } else if (!is_reverse_link && OB_FAIL(schema_checker_->get_dblink_user(tenant_id, dblink_name, - database_name, *allocator_))){ - LOG_WARN("failed to get dblink user name", K(tenant_id), K(database_name)); - } else if (!is_reverse_link && database_name.empty()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("dblink user name is empty", K(ret)); - } else { - ObString tmp_dbname; - if (OB_NOT_NULL(dbname_node)) { - int32_t database_name_len = static_cast(dbname_node->str_len_); - tmp_dbname.assign_ptr(dbname_node->str_value_, database_name_len); - // the one saved in the schema may different from the one in the parse node, check it. - if (0 != database_name.case_compare(tmp_dbname)) { - LOG_DEBUG("user name is not same", K(database_name), K(tmp_dbname)); - database_name = tmp_dbname; - } - } - // database name may lower char, translate to upper, for all_object's user name is upper - // why we use database_name, but not dbname_node, because dbname_node is not always exist - char letter; - char *src_ptr = database_name.ptr(); - for(ObString::obstr_size_t i = 0; i < database_name.length(); ++i) { - letter = src_ptr[i]; - if(letter >= 'a' && letter <= 'z'){ - src_ptr[i] = static_cast(letter - 32); - } + LOG_WARN("cat not find dblink", K(dblink_name), K(ret)); + } else if (FALSE_IT([&]{dblink_id = dblink_schema->get_dblink_id();}())) { + } else if (lib::is_oracle_mode()) { + database_name = dblink_schema->get_user_name(); + if (!tmp_dbname.empty() && 0 != database_name.case_compare(tmp_dbname)) { + database_name = tmp_dbname; + } + char letter; + char *src_ptr = database_name.ptr(); + for(ObString::obstr_size_t i = 0; i < database_name.length(); ++i) { + letter = src_ptr[i]; + if(letter >= 'a' && letter <= 'z'){ + src_ptr[i] = static_cast(letter - 32); } } - if (OB_SUCC(ret)) { - int32_t table_name_len = static_cast(table_node->children_[1]->str_len_); - table_name.assign_ptr(table_node->children_[1]->str_value_, table_name_len); + } else { // mysql dblink + database_name = dblink_schema->get_database_name(); + if (!tmp_dbname.empty() && database_name.case_compare(tmp_dbname)) { + database_name = tmp_dbname; } } + if (OB_SUCC(ret)) { + int32_t table_name_len = static_cast(table_node->children_[1]->str_len_); + table_name.assign_ptr(table_node->children_[1]->str_value_, table_name_len); + } return ret; } @@ -12431,6 +12424,12 @@ int ObDMLResolver::resolve_global_hint(const ParseNode &hint_node, } break; } + case T_FLASHBACK_READ_TX_UNCOMMITTED: { + CHECK_HINT_PARAM(hint_node, 0) { + global_hint.set_flashback_read_tx_uncommitted(true); + } + break; + } case T_NO_GATHER_OPTIMIZER_STATISTICS: { CHECK_HINT_PARAM(hint_node, 0) { global_hint.merge_osg_hint(ObOptimizerStatisticsGatheringHint::OB_NO_OPT_STATS_GATHER); diff --git a/src/sql/resolver/dml/ob_dml_stmt.h b/src/sql/resolver/dml/ob_dml_stmt.h index 158972b96b..172445fb5e 100644 --- a/src/sql/resolver/dml/ob_dml_stmt.h +++ b/src/sql/resolver/dml/ob_dml_stmt.h @@ -203,7 +203,8 @@ struct TableItem K_(dblink_id), K_(dblink_name), K_(link_database_name), K_(is_reverse_link), K_(ddl_schema_version), K_(ddl_table_id), K_(is_view_table), K_(part_ids), K_(part_names), K_(cte_type), - KPC_(function_table_expr), K_(table_type)); + KPC_(function_table_expr), + K_(flashback_query_type), KPC_(flashback_query_expr), K_(table_type)); enum TableType { @@ -243,7 +244,6 @@ struct TableItem USING_TIMESTAMP, USING_SCN }; - //this table resolved from schema, is base table or alias from base table bool is_basic_table() const { return BASE_TABLE == type_ || ALIAS_TABLE == type_; } bool is_generated_table() const { return GENERATED_TABLE == type_; } diff --git a/src/sql/resolver/dml/ob_hint.cpp b/src/sql/resolver/dml/ob_hint.cpp index 7fcddc79e8..fd0323d6f0 100644 --- a/src/sql/resolver/dml/ob_hint.cpp +++ b/src/sql/resolver/dml/ob_hint.cpp @@ -294,7 +294,8 @@ bool ObGlobalHint::has_hint_exclude_concurrent() const || !monitoring_ids_.empty() || !dops_.empty() || !opt_params_.empty() - || !ob_ddl_schema_versions_.empty(); + || !ob_ddl_schema_versions_.empty() + || flashback_read_tx_uncommitted_; } void ObGlobalHint::reset() @@ -326,6 +327,7 @@ void ObGlobalHint::reset() enable_append_ = false; osg_hint_.flags_ = 0; has_dbms_stats_hint_ = false; + flashback_read_tx_uncommitted_ = false; dynamic_sampling_ = ObGlobalHint::UNSET_DYNAMIC_SAMPLING; } @@ -353,6 +355,7 @@ int ObGlobalHint::merge_global_hint(const ObGlobalHint &other) enable_append_ |= other.enable_append_; osg_hint_.flags_ |= other.osg_hint_.flags_; has_dbms_stats_hint_ |= other.has_dbms_stats_hint_; + flashback_read_tx_uncommitted_ |= other.flashback_read_tx_uncommitted_; merge_dynamic_sampling_hint(other.dynamic_sampling_); if (OB_FAIL(merge_monitor_hints(other.monitoring_ids_))) { LOG_WARN("failed to merge monitor hints", K(ret)); @@ -532,6 +535,9 @@ int ObGlobalHint::print_global_hint(PlanText &plan_text, const bool ignore_paral if (OB_SUCC(ret) && has_dbms_stats_hint()) { PRINT_GLOBAL_HINT_STR("DBMS_STATS"); } + if (OB_SUCC(ret) && get_flashback_read_tx_uncommitted()) { + PRINT_GLOBAL_HINT_STR("FLASHBACK_READ_TX_UNCOMMITTED"); + } return ret; } diff --git a/src/sql/resolver/dml/ob_hint.h b/src/sql/resolver/dml/ob_hint.h index 856973f791..f5f9bc5a76 100644 --- a/src/sql/resolver/dml/ob_hint.h +++ b/src/sql/resolver/dml/ob_hint.h @@ -174,6 +174,8 @@ struct ObGlobalHint { bool disable_cost_based_transform() const { return disable_cost_based_transform_; } inline bool has_dbms_stats_hint() const { return has_dbms_stats_hint_; } inline void set_dbms_stats() { has_dbms_stats_hint_ = true; } + bool get_flashback_read_tx_uncommitted() const { return flashback_read_tx_uncommitted_; } + void set_flashback_read_tx_uncommitted(bool v) { flashback_read_tx_uncommitted_ = v; } bool has_append() const { return (osg_hint_.flags_ & ObOptimizerStatisticsGatheringHint::OB_APPEND_HINT) ? true : false; } @@ -261,6 +263,7 @@ struct ObGlobalHint { common::ObSArray ob_ddl_schema_versions_; ObOptimizerStatisticsGatheringHint osg_hint_; bool has_dbms_stats_hint_; + bool flashback_read_tx_uncommitted_; int64_t dynamic_sampling_; }; diff --git a/src/sql/resolver/dml/ob_select_resolver.cpp b/src/sql/resolver/dml/ob_select_resolver.cpp index 921dcd0b06..61dfd646df 100644 --- a/src/sql/resolver/dml/ob_select_resolver.cpp +++ b/src/sql/resolver/dml/ob_select_resolver.cpp @@ -1370,6 +1370,9 @@ int ObSelectResolver::set_for_update_mysql(ObSelectStmt &stmt, const int64_t wai } else if (table_item->is_basic_table()) { table_item->for_update_ = true; table_item->for_update_wait_us_ = wait_us; + } else if (table_item->is_link_table()) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("mysql dblink not support select for update", K(ret)); } } return ret; diff --git a/src/sql/resolver/ob_schema_checker.cpp b/src/sql/resolver/ob_schema_checker.cpp index 8d2bb90182..4694891cb6 100644 --- a/src/sql/resolver/ob_schema_checker.cpp +++ b/src/sql/resolver/ob_schema_checker.cpp @@ -2048,6 +2048,18 @@ int ObSchemaChecker::get_dblink_user(const uint64_t tenant_id, return ret; } +int ObSchemaChecker::get_dblink_schema(uint64_t tenant_id, const common::ObString &dblink_name, const share::schema::ObDbLinkSchema *&dblink_schema) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(schema_mgr_)) { + ret = OB_NOT_INIT; + LOG_WARN("invalid argument", K(ret), K(schema_mgr_)); + } else if (OB_FAIL(schema_mgr_->get_dblink_schema(tenant_id, dblink_name, dblink_schema))) { + LOG_WARN("failed to get dblink schema", K(ret), K(tenant_id), K(dblink_name)); + } + return ret; +} + int ObSchemaChecker::get_directory_id(const uint64_t tenant_id, const common::ObString &directory_name, uint64_t &directory_id) diff --git a/src/sql/resolver/ob_schema_checker.h b/src/sql/resolver/ob_schema_checker.h index d89490c23e..5174e07ee2 100644 --- a/src/sql/resolver/ob_schema_checker.h +++ b/src/sql/resolver/ob_schema_checker.h @@ -504,6 +504,7 @@ public: const common::ObString &dblink_name, common::ObString &dblink_user, common::ObIAllocator &allocator); + int get_dblink_schema(uint64_t tenant_id, const common::ObString &dblink_name, const share::schema::ObDbLinkSchema *&dblink_schema); // directory int get_directory_id(const uint64_t tenant_id, diff --git a/src/sql/resolver/ob_stmt_resolver.cpp b/src/sql/resolver/ob_stmt_resolver.cpp index 8a4900487c..5240a9ec29 100644 --- a/src/sql/resolver/ob_stmt_resolver.cpp +++ b/src/sql/resolver/ob_stmt_resolver.cpp @@ -41,7 +41,8 @@ int ObStmtResolver::resolve_table_relation_node(const ParseNode *node, bool is_org/*false*/, bool is_oracle_sys_view, char **dblink_name_ptr, - int32_t *dblink_name_len) + int32_t *dblink_name_len, + bool *has_dblink_node) { int ret = OB_SUCCESS; bool is_db_explicit = false; @@ -53,7 +54,8 @@ int ObStmtResolver::resolve_table_relation_node(const ParseNode *node, is_org, is_oracle_sys_view, dblink_name_ptr, - dblink_name_len))) { + dblink_name_len, + has_dblink_node))) { LOG_WARN("failed to resolve table name", K(ret)); } else { // do nothing @@ -75,7 +77,8 @@ int ObStmtResolver::resolve_table_relation_node_v2(const ParseNode *node, bool is_org/*false*/, bool is_oracle_sys_view, char **dblink_name_ptr, - int32_t *dblink_name_len) + int32_t *dblink_name_len, + bool *has_dblink_node) { int ret = OB_SUCCESS; is_db_explicit = false; @@ -85,6 +88,12 @@ int ObStmtResolver::resolve_table_relation_node_v2(const ParseNode *node, table_name.assign_ptr(const_cast(relation_node->str_value_), table_len); ObNameCaseMode mode = OB_NAME_CASE_INVALID; ObCollationType cs_type = CS_TYPE_INVALID; + if (OB_NOT_NULL(has_dblink_node)) { + *has_dblink_node = false; + if (node->num_child_ >= 3 && NULL != node->children_[2]) { + *has_dblink_node = true; + } + } if (NULL != dblink_name_ptr && NULL != dblink_name_len && node->num_child_ >= 3 && @@ -170,7 +179,7 @@ int ObStmtResolver::resolve_table_relation_node_v2(const ParseNode *node, return ret; } -int ObStmtResolver::resolve_dblink_name(const ParseNode *table_node, ObString &dblink_name, bool &is_reverse_link, bool &has_dblink_node) +int ObStmtResolver::resolve_dblink_name(const ParseNode *table_node, uint64_t tenant_id, ObString &dblink_name, bool &is_reverse_link, bool &has_dblink_node) { int ret = OB_SUCCESS; dblink_name.reset(); @@ -178,11 +187,24 @@ int ObStmtResolver::resolve_dblink_name(const ParseNode *table_node, ObString &d !OB_ISNULL(table_node->children_) && !OB_ISNULL(table_node->children_[2])) { const ParseNode *dblink_node = table_node->children_[2]; has_dblink_node = true; - if (2 == dblink_node->num_child_ && !OB_ISNULL(dblink_node->children_) && - !OB_ISNULL(dblink_node->children_[0]) && !OB_ISNULL(dblink_node->children_[1])) { + if (!lib::is_oracle_mode()) { + uint64_t compat_version = 0; + if (OB_FAIL(GET_MIN_DATA_VERSION(tenant_id, compat_version))) { + LOG_WARN("fail to get data version", KR(ret), K(tenant_id)); + } else if (compat_version < DATA_VERSION_4_2_0_0) { + ret = OB_NOT_SUPPORTED; + LOG_WARN("mysql dblink is not supported when MIN_DATA_VERSION is below DATA_VERSION_4_2_0_0", K(ret)); + } + } + if (OB_FAIL(ret)) { + // do nothing + } else if (2 == dblink_node->num_child_ && !OB_ISNULL(dblink_node->children_) && + !OB_ISNULL(dblink_node->children_[0])) { int32_t dblink_name_len = static_cast(dblink_node->children_[0]->str_len_); dblink_name.assign_ptr(dblink_node->children_[0]->str_value_, dblink_name_len); - is_reverse_link = dblink_node->children_[1]->value_; + if (!OB_ISNULL(dblink_node->children_[1])) { + is_reverse_link = dblink_node->children_[1]->value_; + } } } return ret; diff --git a/src/sql/resolver/ob_stmt_resolver.h b/src/sql/resolver/ob_stmt_resolver.h index 0f02b6cc21..a122820bd5 100644 --- a/src/sql/resolver/ob_stmt_resolver.h +++ b/src/sql/resolver/ob_stmt_resolver.h @@ -62,7 +62,8 @@ public: bool org = false, bool is_oracle_sys_view = false, char **dblink_name_ptr = NULL, - int32_t *dblink_name_len = NULL); + int32_t *dblink_name_len = NULL, + bool *has_dblink_node = NULL); int resolve_table_relation_node(const ParseNode *node, common::ObString &table_name, @@ -70,7 +71,8 @@ public: bool org = false, bool is_oracle_sys_view = false, char **dblink_name_ptr = NULL, - int32_t *dblink_name_len = NULL); + int32_t *dblink_name_len = NULL, + bool *has_dblink_node = NULL); /** * @brief 解析一个T_REF_FACTOR节点,得到database name和table name * @param [in] node - 语法节点 @@ -84,7 +86,7 @@ public: * */ static int resolve_ref_factor(const ParseNode *node, ObSQLSessionInfo *session_info, common::ObString &table_name, common::ObString &db_name); - static int resolve_dblink_name(const ParseNode *table_node, ObString &dblink_name, bool &is_reverse_link, bool &has_dblink_node); + static int resolve_dblink_name(const ParseNode *table_node, uint64_t tenant_id, ObString &dblink_name, bool &is_reverse_link, bool &has_dblink_node); int resolve_database_factor(const ParseNode *node, uint64_t tenant_id, uint64_t &database_id, diff --git a/src/sql/resolver/ob_stmt_type.h b/src/sql/resolver/ob_stmt_type.h index e2ec6caa01..a90560dcf9 100644 --- a/src/sql/resolver/ob_stmt_type.h +++ b/src/sql/resolver/ob_stmt_type.h @@ -221,8 +221,8 @@ OB_STMT_TYPE_DEF(T_GRANT_ROLE, no_priv_needed, 211, ACTION_TYPE_GRANT_ROLE) OB_STMT_TYPE_DEF(T_REVOKE_ROLE, no_priv_needed, 212, ACTION_TYPE_REVOKE_ROLE) OB_STMT_TYPE_DEF_UNKNOWN_AT(T_MERGE_RESOURCE_POOL, get_sys_tenant_super_priv, 213) OB_STMT_TYPE_DEF_UNKNOWN_AT(T_SHOW_TRIGGERS, err_stmt_type_priv, 214) -OB_STMT_TYPE_DEF_UNKNOWN_AT(T_CREATE_DBLINK, no_priv_needed, 215) -OB_STMT_TYPE_DEF_UNKNOWN_AT(T_DROP_DBLINK, no_priv_needed, 216) +OB_STMT_TYPE_DEF_UNKNOWN_AT(T_CREATE_DBLINK, get_create_dblink_priv, 215) +OB_STMT_TYPE_DEF_UNKNOWN_AT(T_DROP_DBLINK, get_drop_dblink_priv, 216) OB_STMT_TYPE_DEF(T_CREATE_PUB_SYNONYM, get_create_synonym_priv, 217, ACTION_TYPE_CREATE_PUBLIC_SYNONYM) OB_STMT_TYPE_DEF(T_DROP_PUB_SYNONYM, get_drop_synonym_priv, 218, ACTION_TYPE_DROP_PUBLIC_SYNONYM) OB_STMT_TYPE_DEF(T_CREATE_PROFILE, no_priv_needed, 219, ACTION_TYPE_CREATE_PROFILE) diff --git a/src/sql/rewrite/ob_transform_dblink.cpp b/src/sql/rewrite/ob_transform_dblink.cpp index 20b13c4f3b..8c824f37cf 100644 --- a/src/sql/rewrite/ob_transform_dblink.cpp +++ b/src/sql/rewrite/ob_transform_dblink.cpp @@ -419,6 +419,8 @@ int ObTransformDBlink::pack_link_table(ObDMLStmt *stmt, bool &trans_happened) if (OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpect null stmt", K(ret)); + } else if (OB_FAIL(add_flashback_query_for_dblink(stmt))) { + LOG_WARN("add flashback query for dblink failed", K(ret)); } else if (OB_FAIL(collect_link_table(stmt, helpers, dblink_id, @@ -1455,5 +1457,77 @@ int ObTransformDBlink::check_link_oracle(int64_t dblink_id, bool &link_oracle) return ret; } +int ObTransformDBlink::add_flashback_query_for_dblink(ObDMLStmt *stmt) +{ + int ret = OB_SUCCESS; + share::schema::ObSchemaGetterGuard *schema_guard = NULL; + const ObDbLinkSchema *dblink_schema = NULL; + ObConstRawExpr *c_expr = NULL; + uint64_t current_scn = OB_INVALID_ID; + bool need_add = false; + uint64_t tenant_id = OB_INVALID_ID; + if (OB_ISNULL(ctx_) || + OB_ISNULL(ctx_->sql_schema_guard_) || + OB_ISNULL(ctx_->session_info_) || + OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null param", K(ret), K(ctx_), K(stmt)); + } else { + tenant_id = ctx_->session_info_->get_effective_tenant_id(); + for (int64_t i = 0; i < stmt->get_table_items().count() && OB_SUCC(ret); i++) { + TableItem *table_item = stmt->get_table_item(i); + uint64_t dblink_id = OB_INVALID_ID; + bool need_add = false; + if (OB_ISNULL(table_item)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null param", K(ret)); + } else if (!table_item->is_link_table() + || TableItem::NOT_USING != table_item->flashback_query_type_) { + // do nothing if not dblink table or already have flashback query + } else if (FALSE_IT(dblink_id = table_item->dblink_id_)) { + } else if (table_item->is_reverse_link_) { + need_add = true; + } else if (OB_FAIL(ctx_->sql_schema_guard_->get_dblink_schema(tenant_id, dblink_id, dblink_schema))) { + LOG_WARN("failed to get dblink schema", K(ret), K(tenant_id), K(dblink_id)); + } else if (OB_ISNULL(dblink_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("dblink schema is null", K(ret), K(tenant_id), K(dblink_id), KPC(table_item)); + } else if (static_cast(dblink_schema->get_driver_proto()) != common::sqlclient::DBLINK_DRV_OB) { + // do nothing if not connect to ob + } else { + need_add = true; + } + if (OB_FAIL(ret) || !need_add) { + } else if (OB_ISNULL(stmt->get_query_ctx()) || OB_ISNULL(ctx_->expr_factory_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("query ctx or expr factory is null", K(ret), K(stmt->get_query_ctx()), + K(ctx_->expr_factory_)); + } else if (OB_FAIL(stmt->get_query_ctx()->sql_schema_guard_.get_link_current_scn(dblink_id, + tenant_id, ctx_->session_info_, current_scn))) { + if (OB_HASH_NOT_EXIST == ret) { + ret = OB_SUCCESS; + } else { + LOG_WARN("get dblink current scn failed", K(ret), K(dblink_id)); + } + } else if (OB_INVALID_ID == current_scn) { + // remote server not support current_scn function, do nothing + } else if (OB_FAIL(ctx_->expr_factory_->create_raw_expr(T_INT, c_expr))) { + LOG_WARN("fail to create raw expr", K(ret)); + } else if (OB_ISNULL(c_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("const expr is null"); + } else { + ObObj val; + val.set_uint64(current_scn); + c_expr->set_value(val); + c_expr->set_param(val); + table_item->flashback_query_expr_ = c_expr; + table_item->flashback_query_type_ = TableItem::USING_SCN; + } + } + } + return ret; +} + } } diff --git a/src/sql/rewrite/ob_transform_dblink.h b/src/sql/rewrite/ob_transform_dblink.h index d948223359..9c23d98357 100644 --- a/src/sql/rewrite/ob_transform_dblink.h +++ b/src/sql/rewrite/ob_transform_dblink.h @@ -162,6 +162,8 @@ private: int check_link_oracle(int64_t dblink_id, bool &link_oracle); + int add_flashback_query_for_dblink(ObDMLStmt *stmt); + int has_invalid_link_expr(ObDMLStmt &stmt, bool &has_invalid_expr); DISALLOW_COPY_AND_ASSIGN(ObTransformDBlink); diff --git a/src/storage/access/ob_dml_param.cpp b/src/storage/access/ob_dml_param.cpp index c6334e28b4..ae01ef077a 100644 --- a/src/storage/access/ob_dml_param.cpp +++ b/src/storage/access/ob_dml_param.cpp @@ -291,6 +291,7 @@ DEF_TO_STRING(ObTableScanParam) K_(sample_info), K_(need_scn), K_(need_switch_param), + K_(fb_read_tx_uncommitted), K_(external_file_format), K_(external_file_location)); J_OBJ_END(); diff --git a/src/storage/access/ob_dml_param.h b/src/storage/access/ob_dml_param.h index 31bdc605a0..31334defbd 100644 --- a/src/storage/access/ob_dml_param.h +++ b/src/storage/access/ob_dml_param.h @@ -130,6 +130,7 @@ public: : common::ObVTableScanParam(), trans_desc_(NULL), snapshot_(), + fb_read_tx_uncommitted_(false), tx_id_(), tx_lock_timeout_(-1), table_param_(NULL), @@ -143,6 +144,7 @@ public: public: transaction::ObTxDesc *trans_desc_; // transaction handle transaction::ObTxReadSnapshot snapshot_; + bool fb_read_tx_uncommitted_; transaction::ObTransID tx_id_; // used when read-latest int64_t tx_lock_timeout_; const share::schema::ObTableParam *table_param_; diff --git a/src/storage/tx/ob_trans_define_v4.cpp b/src/storage/tx/ob_trans_define_v4.cpp index 130e089673..7b07ef6f93 100644 --- a/src/storage/tx/ob_trans_define_v4.cpp +++ b/src/storage/tx/ob_trans_define_v4.cpp @@ -1085,6 +1085,12 @@ void ObTxReadSnapshot::init_ls_read(const share::ObLSID &ls_id, const ObTxSnapsh valid_ = true; } +void ObTxReadSnapshot::specify_snapshot_scn(const share::SCN snapshot) +{ + core_.version_ = snapshot; + source_ = SRC::SPECIAL; +} + void ObTxReadSnapshot::wait_consistency() { if (SRC::GLOBAL == source_) { diff --git a/src/storage/tx/ob_trans_define_v4.h b/src/storage/tx/ob_trans_define_v4.h index ec6deb512f..1242333a26 100644 --- a/src/storage/tx/ob_trans_define_v4.h +++ b/src/storage/tx/ob_trans_define_v4.h @@ -234,6 +234,7 @@ struct ObTxReadSnapshot void init_special_read(const share::SCN snapshot); void init_none_read() { valid_ = true; source_ = SRC::NONE; } void init_ls_read(const share::ObLSID &ls_id, const ObTxSnapshot &core); + void specify_snapshot_scn(const share::SCN snapshot); void wait_consistency(); ObString get_source_name() const; bool is_weak_read() const { return SRC::WEAK_READ_SERVICE == source_; }; diff --git a/src/storage/tx_storage/ob_access_service.cpp b/src/storage/tx_storage/ob_access_service.cpp index 61c49e404b..8845f56612 100644 --- a/src/storage/tx_storage/ob_access_service.cpp +++ b/src/storage/tx_storage/ob_access_service.cpp @@ -396,6 +396,7 @@ int ObAccessService::check_read_allowed_( { int ret = OB_SUCCESS; ObLS *ls = nullptr; + LOG_TRACE("print check read allowed, scan param", K(ls_id), K(tablet_id), K(scan_param.fb_read_tx_uncommitted_)); if (OB_FAIL(ctx_guard.init(ls_id))) { LOG_WARN("ctx_guard init fail", K(ret), K(ls_id)); } else if (OB_FAIL(ls_svr_->get_ls(ls_id, ctx_guard.get_ls_handle(), ObLSGetMod::DAS_MOD))) { @@ -408,7 +409,7 @@ int ObAccessService::check_read_allowed_( ctx.ls_ = ls; ctx.timeout_ = scan_param.timeout_; ctx.tablet_id_ = tablet_id; - if (user_specified_snapshot.is_valid()) { + if (user_specified_snapshot.is_valid() && !scan_param.fb_read_tx_uncommitted_) { if (OB_FAIL(ls->get_read_store_ctx(user_specified_snapshot, scan_param.tx_lock_timeout_, ctx))) { @@ -416,12 +417,24 @@ int ObAccessService::check_read_allowed_( } } else { bool read_latest = access_type == ObStoreAccessType::READ_LATEST; - auto &snapshot = scan_param.snapshot_; - if (OB_FAIL(ls->get_read_store_ctx(snapshot, - read_latest, - scan_param.tx_lock_timeout_, - ctx))) { - LOG_WARN("get read store ctx fail", K(read_latest), K(snapshot), K(ls_id), K(ret)); + if (user_specified_snapshot.is_valid()) { + transaction::ObTxReadSnapshot spec_snapshot; + if (OB_FAIL(spec_snapshot.assign(scan_param.snapshot_))) { + LOG_WARN("copy snapshot fail", K(ret)); + } else if (FALSE_IT(spec_snapshot.specify_snapshot_scn(user_specified_snapshot))) { + } else if (OB_FAIL(ls->get_read_store_ctx(spec_snapshot, + read_latest, + scan_param.tx_lock_timeout_, + ctx))) { + LOG_WARN("get read store ctx fail", K(ret), K(read_latest), K(spec_snapshot), K(user_specified_snapshot), K(ls_id)); + } + } else if (OB_FAIL(ls->get_read_store_ctx(scan_param.snapshot_, + read_latest, + scan_param.tx_lock_timeout_, + ctx))) { + LOG_WARN("get read store ctx fail", K(ret), K(read_latest), K(scan_param.snapshot_), K(ls_id)); + } + if (OB_FAIL(ret)) { } else if (read_latest) { if (!scan_param.tx_id_.is_valid()) { ret = OB_INVALID_ARGUMENT; @@ -453,52 +466,6 @@ int ObAccessService::check_read_allowed_( return ret; } -/* - * check_read_allowed - check replica can serve read - * - * NOTE: this function only be used by DML pre-check conflict - * it's better to use SCAN_PARAM + SNAPSHOT in the future - */ -int ObAccessService::check_read_allowed_( - const share::ObLSID &ls_id, - const common::ObTabletID &tablet_id, - const ObStoreAccessType access_type, - const ObDMLBaseParam &dml_param, - const transaction::ObTxDesc &tx_desc, - const transaction::ObTxReadSnapshot &snapshot, - ObStoreCtxGuard &ctx_guard) -{ - int ret = OB_SUCCESS; - ObLS *ls = nullptr; - if (OB_FAIL(ctx_guard.init(ls_id))) { - LOG_WARN("ctx_guard init fail", K(ret), K(ls_id), K(tx_desc)); - } else if (OB_FAIL(ls_svr_->get_ls(ls_id, ctx_guard.get_ls_handle(), ObLSGetMod::DAS_MOD))) { - LOG_WARN("get log stream failed.", K(ret), K(ls_id)); - } else if (OB_ISNULL(ls = ctx_guard.get_ls_handle().get_ls())) { - ret = OB_ERR_UNEXPECTED; - LOG_ERROR("ls should not be null", K(ret), K(ls_id), K_(tenant_id)); - } else { - auto &ctx = ctx_guard.get_store_ctx(); - ctx.ls_ = ls; - ctx.timeout_ = dml_param.timeout_; - ctx.tablet_id_ = tablet_id; - bool read_latest = access_type == ObStoreAccessType::READ_LATEST; - if (OB_FAIL(ls->get_read_store_ctx(snapshot, - read_latest, - tx_desc.get_tx_lock_timeout(), - ctx))) { - LOG_WARN("get read store ctx fail", K(read_latest), K(snapshot), K(ls_id), K(ret)); - } else if (read_latest) { - if (!tx_desc.get_tx_id().is_valid()) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("readlatest need trans_desc.tx_id_ valid", K(ret)); - } else { - ctx.mvcc_acc_ctx_.tx_id_ = tx_desc.get_tx_id(); - } - } - } - return ret; -} /* * check_write_allowed - check replica can serve transactional write diff --git a/src/storage/tx_storage/ob_access_service.h b/src/storage/tx_storage/ob_access_service.h index a6d98cc78d..edf88e3ae8 100644 --- a/src/storage/tx_storage/ob_access_service.h +++ b/src/storage/tx_storage/ob_access_service.h @@ -213,14 +213,6 @@ protected: const ObTableScanParam &scan_param, ObStoreCtxGuard &ctx_guard, share::SCN user_specified_snapshot); - int check_read_allowed_( - const share::ObLSID &ls_id, - const common::ObTabletID &tablet_id, - const ObStoreAccessType access_type, - const ObDMLBaseParam &dml_param, - const transaction::ObTxDesc &tx_desc, - const transaction::ObTxReadSnapshot &snapshot, - ObStoreCtxGuard &ctx_guard); int check_write_allowed_( const share::ObLSID &ls_id, const common::ObTabletID &tablet_id, diff --git a/tools/deploy/mysql_test/test_suite/information_schema/r/mysql/information_schema_desc.result b/tools/deploy/mysql_test/test_suite/information_schema/r/mysql/information_schema_desc.result index 51b41afbe1..42a0ec63c7 100644 --- a/tools/deploy/mysql_test/test_suite/information_schema/r/mysql/information_schema_desc.result +++ b/tools/deploy/mysql_test/test_suite/information_schema/r/mysql/information_schema_desc.result @@ -283,7 +283,7 @@ View Create View character_set_client collation_connection TABLES CREATE VIEW `TABLES` AS select /*+ leading(a) no_use_nl(ts)*/ cast('def' as char(512)) as TABLE_CATALOG, cast(b.database_name as char(64)) as TABLE_SCHEMA, cast(a.table_name as char(64)) as TABLE_NAME, cast(case when (a.database_id = 201002 or a.table_type = 1) then 'SYSTEM VIEW' when a.table_type in (0, 2) then 'SYSTEM TABLE' when a.table_type = 4 then 'VIEW' else 'BASE TABLE' end as char(64)) as TABLE_TYPE, cast(NULL as char(64)) as ENGINE, cast(NULL as unsigned) as VERSION, cast(NULL as char(10)) as ROW_FORMAT, cast( coalesce(ts.row_cnt,0) as unsigned) as TABLE_ROWS, cast( coalesce(ts.avg_row_len,0) as unsigned) as AVG_ROW_LENGTH, cast( coalesce(ts.data_size,0) as unsigned) as DATA_LENGTH, cast(NULL as unsigned) as MAX_DATA_LENGTH, cast(NULL as unsigned) as INDEX_LENGTH, cast(NULL as unsigned) as DATA_FREE, cast(NULL as unsigned) as AUTO_INCREMENT, cast(a.gmt_create as datetime) as CREATE_TIME, cast(a.gmt_modified as datetime) as UPDATE_TIME, cast(NULL as datetime) as CHECK_TIME, cast(d.collation as char(32)) as TABLE_COLLATION, cast(NULL as unsigned) as CHECKSUM, cast(NULL as char(255)) as CREATE_OPTIONS, cast(case when a.table_type = 4 then 'VIEW' else a.comment end as char(2048)) as TABLE_COMMENT from ( select cast(0 as signed) as tenant_id, c.database_id, c.table_id, c.table_name, c.collation_type, c.table_type, usec_to_time(d.schema_version) as gmt_create, usec_to_time(c.schema_version) as gmt_modified, c.comment from oceanbase.__all_virtual_core_all_table c join oceanbase.__all_virtual_core_all_table d on c.tenant_id = d.tenant_id and d.table_name = '__all_core_table' where c.tenant_id = effective_tenant_id() union all select tenant_id, database_id, table_id, table_name, collation_type, table_type, gmt_create, gmt_modified, comment from oceanbase.__all_table) a join oceanbase.__all_database b on a.database_id = b.database_id and a.tenant_id = b.tenant_id join oceanbase.__tenant_virtual_collation d on a.collation_type = d.collation_type left join ( select tenant_id, table_id, sum(row_cnt) as row_cnt, sum(row_cnt * avg_row_len) / sum(row_cnt) as avg_row_len, sum(row_cnt * avg_row_len) as data_size from oceanbase.__all_table_stat group by tenant_id, table_id) ts on a.table_id = ts.table_id and a.tenant_id = ts.tenant_id where a.tenant_id = 0 and a.table_type in (0, 1, 2, 3, 4, 14) and b.database_name != '__recyclebin' and b.in_recyclebin = 0 and 0 = sys_privilege_check('table_acc', effective_tenant_id(), b.database_name, a.table_name) utf8mb4 utf8mb4_general_ci show create table user_privileges; View Create View character_set_client collation_connection -USER_PRIVILEGES CREATE VIEW `USER_PRIVILEGES` AS SELECT CAST(CONCAT('''', V.USER_NAME, '''', '@', '''', V.HOST, '''') AS CHAR(81)) AS GRANTEE , CAST('def' AS CHAR(512)) AS TABLE_CATALOG , CAST(V.PRIVILEGE_TYPE AS CHAR(64)) AS PRIVILEGE_TYPE , CAST(V.IS_GRANTABLE AS CHAR(3)) AS IS_GRANTABLE FROM (SELECT U.USER_NAME AS USER_NAME, U.HOST AS HOST, CASE WHEN V1.C1 = 1 AND U.PRIV_ALTER = 1 THEN 'ALTER' WHEN V1.C1 = 2 AND U.PRIV_CREATE = 1 THEN 'CREATE' WHEN V1.C1 = 3 AND U.PRIV_CREATE_USER = 1 THEN 'CREATE USER' WHEN V1.C1 = 4 AND U.PRIV_DELETE = 1 THEN 'DELETE' WHEN V1.C1 = 5 AND U.PRIV_DROP = 1 THEN 'DROP' WHEN V1.C1 = 7 AND U.PRIV_INSERT = 1 THEN 'INSERT' WHEN V1.C1 = 8 AND U.PRIV_UPDATE = 1 THEN 'UPDATE' WHEN V1.C1 = 9 AND U.PRIV_SELECT = 1 THEN 'SELECT' WHEN V1.C1 = 10 AND U.PRIV_INDEX = 1 THEN 'INDEX' WHEN V1.C1 = 11 AND U.PRIV_CREATE_VIEW = 1 THEN 'CREATE VIEW' WHEN V1.C1 = 12 AND U.PRIV_SHOW_VIEW = 1 THEN 'SHOW VIEW' WHEN V1.C1 = 13 AND U.PRIV_SHOW_DB = 1 THEN 'SHOW DB' WHEN V1.C1 = 14 AND U.PRIV_SUPER = 1 THEN 'SUPER' WHEN V1.C1 = 15 AND U.PRIV_PROCESS = 1 THEN 'PROCESS' WHEN V1.C1 = 17 AND U.PRIV_CREATE_SYNONYM = 1 THEN 'CREATE SYNONYM' WHEN V1.C1 = 27 AND U.PRIV_FILE = 1 THEN 'FILE' WHEN V1.C1 = 28 AND U.PRIV_ALTER_TENANT = 1 THEN 'ALTER TENANT' WHEN V1.C1 = 29 AND U.PRIV_ALTER_SYSTEM = 1 THEN 'ALTER SYSTEM' WHEN V1.C1 = 30 AND U.PRIV_CREATE_RESOURCE_POOL = 1 THEN 'CREATE RESOURCE POOL' WHEN V1.C1 = 31 AND U.PRIV_CREATE_RESOURCE_UNIT = 1 THEN 'CREATE RESOURCE UNIT' WHEN V1.C1 = 33 AND U.PRIV_REPL_SLAVE = 1 THEN 'REPLICATION SLAVE' WHEN V1.C1 = 34 AND U.PRIV_REPL_CLIENT = 1 THEN 'REPLICATION CLIENT' WHEN V1.C1 = 0 AND U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 AND U.PRIV_CREATE_USER = 0 AND U.PRIV_DELETE = 0 AND U.PRIV_DROP = 0 AND U.PRIV_INSERT = 0 AND U.PRIV_UPDATE = 0 AND U.PRIV_SELECT = 0 AND U.PRIV_INDEX = 0 AND U.PRIV_CREATE_VIEW = 0 AND U.PRIV_SHOW_VIEW = 0 AND U.PRIV_SHOW_DB = 0 AND U.PRIV_SUPER = 0 AND U.PRIV_PROCESS = 0 AND U.PRIV_CREATE_SYNONYM = 0 AND U.PRIV_FILE = 0 AND U.PRIV_ALTER_TENANT = 0 AND U.PRIV_ALTER_SYSTEM = 0 AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 AND U.PRIV_REPL_CLIENT = 0 THEN 'USAGE' END PRIVILEGE_TYPE , CASE WHEN U.PRIV_GRANT_OPTION = 0 THEN 'NO' WHEN U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 AND U.PRIV_CREATE_USER = 0 AND U.PRIV_DELETE = 0 AND U.PRIV_DROP = 0 AND U.PRIV_INSERT = 0 AND U.PRIV_UPDATE = 0 AND U.PRIV_SELECT = 0 AND U.PRIV_INDEX = 0 AND U.PRIV_CREATE_VIEW = 0 AND U.PRIV_SHOW_VIEW = 0 AND U.PRIV_SHOW_DB = 0 AND U.PRIV_SUPER = 0 AND U.PRIV_PROCESS = 0 AND U.PRIV_CREATE_SYNONYM = 0 AND U.PRIV_FILE = 0 AND U.PRIV_ALTER_TENANT = 0 AND U.PRIV_ALTER_SYSTEM = 0 AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 AND U.PRIV_REPL_CLIENT = 0 THEN 'NO' WHEN U.PRIV_GRANT_OPTION = 1 THEN 'YES' END IS_GRANTABLE FROM oceanbase.__all_user U, (SELECT 0 AS C1 UNION ALL SELECT 1 AS C1 UNION ALL SELECT 2 AS C1 UNION ALL SELECT 3 AS C1 UNION ALL SELECT 4 AS C1 UNION ALL SELECT 5 AS C1 UNION ALL SELECT 7 AS C1 UNION ALL SELECT 8 AS C1 UNION ALL SELECT 9 AS C1 UNION ALL SELECT 10 AS C1 UNION ALL SELECT 11 AS C1 UNION ALL SELECT 12 AS C1 UNION ALL SELECT 13 AS C1 UNION ALL SELECT 14 AS C1 UNION ALL SELECT 15 AS C1 UNION ALL SELECT 17 AS C1 UNION ALL SELECT 27 AS C1 UNION ALL SELECT 28 AS C1 UNION ALL SELECT 29 AS C1 UNION ALL SELECT 30 AS C1 UNION ALL SELECT 31 AS C1 UNION ALL SELECT 33 AS C1 UNION ALL SELECT 34 AS C1) V1, (SELECT USER_ID FROM oceanbase.__all_user WHERE TENANT_ID = 0 AND CONCAT(USER_NAME, '@', HOST) = CURRENT_USER()) CURR LEFT JOIN (SELECT USER_ID FROM oceanbase.__all_database_privilege WHERE TENANT_ID = 0 AND DATABASE_NAME = 'mysql' AND PRIV_SELECT = 1) DB ON CURR.USER_ID = DB.USER_ID WHERE U.TENANT_ID = 0 AND (DB.USER_ID IS NOT NULL OR 512 & CURRENT_USER_PRIV() = 512 OR U.USER_ID = CURR.USER_ID)) V WHERE V.PRIVILEGE_TYPE IS NOT NULL utf8mb4 utf8mb4_general_ci +USER_PRIVILEGES CREATE VIEW `USER_PRIVILEGES` AS SELECT CAST(CONCAT('''', V.USER_NAME, '''', '@', '''', V.HOST, '''') AS CHAR(81)) AS GRANTEE , CAST('def' AS CHAR(512)) AS TABLE_CATALOG , CAST(V.PRIVILEGE_TYPE AS CHAR(64)) AS PRIVILEGE_TYPE , CAST(V.IS_GRANTABLE AS CHAR(3)) AS IS_GRANTABLE FROM (SELECT U.USER_NAME AS USER_NAME, U.HOST AS HOST, CASE WHEN V1.C1 = 1 AND U.PRIV_ALTER = 1 THEN 'ALTER' WHEN V1.C1 = 2 AND U.PRIV_CREATE = 1 THEN 'CREATE' WHEN V1.C1 = 3 AND U.PRIV_CREATE_USER = 1 THEN 'CREATE USER' WHEN V1.C1 = 4 AND U.PRIV_DELETE = 1 THEN 'DELETE' WHEN V1.C1 = 5 AND U.PRIV_DROP = 1 THEN 'DROP' WHEN V1.C1 = 7 AND U.PRIV_INSERT = 1 THEN 'INSERT' WHEN V1.C1 = 8 AND U.PRIV_UPDATE = 1 THEN 'UPDATE' WHEN V1.C1 = 9 AND U.PRIV_SELECT = 1 THEN 'SELECT' WHEN V1.C1 = 10 AND U.PRIV_INDEX = 1 THEN 'INDEX' WHEN V1.C1 = 11 AND U.PRIV_CREATE_VIEW = 1 THEN 'CREATE VIEW' WHEN V1.C1 = 12 AND U.PRIV_SHOW_VIEW = 1 THEN 'SHOW VIEW' WHEN V1.C1 = 13 AND U.PRIV_SHOW_DB = 1 THEN 'SHOW DB' WHEN V1.C1 = 14 AND U.PRIV_SUPER = 1 THEN 'SUPER' WHEN V1.C1 = 15 AND U.PRIV_PROCESS = 1 THEN 'PROCESS' WHEN V1.C1 = 17 AND U.PRIV_CREATE_SYNONYM = 1 THEN 'CREATE SYNONYM' WHEN V1.C1 = 27 AND U.PRIV_FILE = 1 THEN 'FILE' WHEN V1.C1 = 28 AND U.PRIV_ALTER_TENANT = 1 THEN 'ALTER TENANT' WHEN V1.C1 = 29 AND U.PRIV_ALTER_SYSTEM = 1 THEN 'ALTER SYSTEM' WHEN V1.C1 = 30 AND U.PRIV_CREATE_RESOURCE_POOL = 1 THEN 'CREATE RESOURCE POOL' WHEN V1.C1 = 31 AND U.PRIV_CREATE_RESOURCE_UNIT = 1 THEN 'CREATE RESOURCE UNIT' WHEN V1.C1 = 33 AND U.PRIV_REPL_SLAVE = 1 THEN 'REPLICATION SLAVE' WHEN V1.C1 = 34 AND U.PRIV_REPL_CLIENT = 1 THEN 'REPLICATION CLIENT' WHEN V1.C1 = 35 AND U.PRIV_DROP_DATABASE_LINK = 1 THEN 'DROP DATABASE LINK' WHEN V1.C1 = 36 AND U.PRIV_CREATE_DATABASE_LINK = 1 THEN 'CREATE DATABASE LINK' WHEN V1.C1 = 0 AND U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 AND U.PRIV_CREATE_USER = 0 AND U.PRIV_DELETE = 0 AND U.PRIV_DROP = 0 AND U.PRIV_INSERT = 0 AND U.PRIV_UPDATE = 0 AND U.PRIV_SELECT = 0 AND U.PRIV_INDEX = 0 AND U.PRIV_CREATE_VIEW = 0 AND U.PRIV_SHOW_VIEW = 0 AND U.PRIV_SHOW_DB = 0 AND U.PRIV_SUPER = 0 AND U.PRIV_PROCESS = 0 AND U.PRIV_CREATE_SYNONYM = 0 AND U.PRIV_FILE = 0 AND U.PRIV_ALTER_TENANT = 0 AND U.PRIV_ALTER_SYSTEM = 0 AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 AND U.PRIV_REPL_CLIENT = 0 AND U.PRIV_DROP_DATABASE_LINK = 0 AND U.PRIV_CREATE_DATABASE_LINK = 0 THEN 'USAGE' END PRIVILEGE_TYPE , CASE WHEN U.PRIV_GRANT_OPTION = 0 THEN 'NO' WHEN U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 AND U.PRIV_CREATE_USER = 0 AND U.PRIV_DELETE = 0 AND U.PRIV_DROP = 0 AND U.PRIV_INSERT = 0 AND U.PRIV_UPDATE = 0 AND U.PRIV_SELECT = 0 AND U.PRIV_INDEX = 0 AND U.PRIV_CREATE_VIEW = 0 AND U.PRIV_SHOW_VIEW = 0 AND U.PRIV_SHOW_DB = 0 AND U.PRIV_SUPER = 0 AND U.PRIV_PROCESS = 0 AND U.PRIV_CREATE_SYNONYM = 0 AND U.PRIV_FILE = 0 AND U.PRIV_ALTER_TENANT = 0 AND U.PRIV_ALTER_SYSTEM = 0 AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 AND U.PRIV_REPL_CLIENT = 0 AND U.PRIV_DROP_DATABASE_LINK = 0 AND U.PRIV_CREATE_DATABASE_LINK = 0 THEN 'NO' WHEN U.PRIV_GRANT_OPTION = 1 THEN 'YES' END IS_GRANTABLE FROM oceanbase.__all_user U, (SELECT 0 AS C1 UNION ALL SELECT 1 AS C1 UNION ALL SELECT 2 AS C1 UNION ALL SELECT 3 AS C1 UNION ALL SELECT 4 AS C1 UNION ALL SELECT 5 AS C1 UNION ALL SELECT 7 AS C1 UNION ALL SELECT 8 AS C1 UNION ALL SELECT 9 AS C1 UNION ALL SELECT 10 AS C1 UNION ALL SELECT 11 AS C1 UNION ALL SELECT 12 AS C1 UNION ALL SELECT 13 AS C1 UNION ALL SELECT 14 AS C1 UNION ALL SELECT 15 AS C1 UNION ALL SELECT 17 AS C1 UNION ALL SELECT 27 AS C1 UNION ALL SELECT 28 AS C1 UNION ALL SELECT 29 AS C1 UNION ALL SELECT 30 AS C1 UNION ALL SELECT 31 AS C1 UNION ALL SELECT 33 AS C1 UNION ALL SELECT 34 AS C1 UNION ALL SELECT 35 AS C1 UNION ALL SELECT 36 AS C1) V1, (SELECT USER_ID FROM oceanbase.__all_user WHERE TENANT_ID = 0 AND CONCAT(USER_NAME, '@', HOST) = CURRENT_USER()) CURR LEFT JOIN (SELECT USER_ID FROM oceanbase.__all_database_privilege WHERE TENANT_ID = 0 AND DATABASE_NAME = 'mysql' AND PRIV_SELECT = 1) DB ON CURR.USER_ID = DB.USER_ID WHERE U.TENANT_ID = 0 AND (DB.USER_ID IS NOT NULL OR 512 & CURRENT_USER_PRIV() = 512 OR U.USER_ID = CURR.USER_ID)) V WHERE V.PRIVILEGE_TYPE IS NOT NULL utf8mb4 utf8mb4_general_ci show create table views; View Create View character_set_client collation_connection VIEWS CREATE VIEW `VIEWS` AS select cast('def' as CHAR(64)) AS TABLE_CATALOG, d.database_name as TABLE_SCHEMA, t.table_name as TABLE_NAME, t.view_definition as VIEW_DEFINITION, case t.view_check_option when 1 then 'LOCAL' when 2 then 'CASCADED' else 'NONE' end as CHECK_OPTION, case t.view_is_updatable when 1 then 'YES' else 'NO' end as IS_UPDATABLE, cast((case t.define_user_id when -1 then 'NONE' else concat(u.user_name, '@', u.host) end) as CHAR(288)) as DEFINER, cast('NONE' as CHAR(7)) AS SECURITY_TYPE, cast((case t.collation_type when 45 then 'utf8mb4' else 'NONE' end) as CHAR(64)) AS CHARACTER_SET_CLIENT, cast((case t.collation_type when 45 then 'utf8mb4_general_ci' else 'NONE' end) as CHAR(64)) AS COLLATION_CONNECTION from oceanbase.__all_table as t join oceanbase.__all_database as d on t.tenant_id = d.tenant_id and t.database_id = d.database_id left join oceanbase.__all_user as u on t.tenant_id = u.tenant_id and t.define_user_id = u.user_id and t.define_user_id != -1 where t.tenant_id = 0 and t.table_type in (1, 4) and d.in_recyclebin = 0 and d.database_name != '__recyclebin' and d.database_name != 'information_schema' and d.database_name != 'oceanbase' and 0 = sys_privilege_check('table_acc', effective_tenant_id(), d.database_name, t.table_name) utf8mb4 utf8mb4_general_ci diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/inner_table_overall.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/inner_table_overall.result index e68b65cc1b..d17567f54b 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/inner_table_overall.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/inner_table_overall.result @@ -915,6 +915,7 @@ select 0xffffffffff & table_id, table_name, table_type, database_id, part_num fr 21422 V$SQL_JOIN_FILTER 1 201001 1 21423 DBA_OB_TABLE_STAT_STALE_INFO 1 201001 1 21425 CDB_OB_EXTERNAL_TABLE_FILES 1 201001 1 +21426 DBA_DB_LINKS 1 201001 1 check sys table count and table_id range success check count and table_id range for virtual table success select * from information_schema.CHARACTER_SETS limit 1; diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/user_privileges.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/user_privileges.result index 4f499074e0..d4db49a2fc 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/user_privileges.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/user_privileges.result @@ -1,6 +1,6 @@ show create table information_schema.user_privileges; View Create View character_set_client collation_connection -USER_PRIVILEGES CREATE VIEW `USER_PRIVILEGES` AS SELECT CAST(CONCAT('''', V.USER_NAME, '''', '@', '''', V.HOST, '''') AS CHAR(81)) AS GRANTEE , CAST('def' AS CHAR(512)) AS TABLE_CATALOG , CAST(V.PRIVILEGE_TYPE AS CHAR(64)) AS PRIVILEGE_TYPE , CAST(V.IS_GRANTABLE AS CHAR(3)) AS IS_GRANTABLE FROM (SELECT U.USER_NAME AS USER_NAME, U.HOST AS HOST, CASE WHEN V1.C1 = 1 AND U.PRIV_ALTER = 1 THEN 'ALTER' WHEN V1.C1 = 2 AND U.PRIV_CREATE = 1 THEN 'CREATE' WHEN V1.C1 = 3 AND U.PRIV_CREATE_USER = 1 THEN 'CREATE USER' WHEN V1.C1 = 4 AND U.PRIV_DELETE = 1 THEN 'DELETE' WHEN V1.C1 = 5 AND U.PRIV_DROP = 1 THEN 'DROP' WHEN V1.C1 = 7 AND U.PRIV_INSERT = 1 THEN 'INSERT' WHEN V1.C1 = 8 AND U.PRIV_UPDATE = 1 THEN 'UPDATE' WHEN V1.C1 = 9 AND U.PRIV_SELECT = 1 THEN 'SELECT' WHEN V1.C1 = 10 AND U.PRIV_INDEX = 1 THEN 'INDEX' WHEN V1.C1 = 11 AND U.PRIV_CREATE_VIEW = 1 THEN 'CREATE VIEW' WHEN V1.C1 = 12 AND U.PRIV_SHOW_VIEW = 1 THEN 'SHOW VIEW' WHEN V1.C1 = 13 AND U.PRIV_SHOW_DB = 1 THEN 'SHOW DB' WHEN V1.C1 = 14 AND U.PRIV_SUPER = 1 THEN 'SUPER' WHEN V1.C1 = 15 AND U.PRIV_PROCESS = 1 THEN 'PROCESS' WHEN V1.C1 = 17 AND U.PRIV_CREATE_SYNONYM = 1 THEN 'CREATE SYNONYM' WHEN V1.C1 = 27 AND U.PRIV_FILE = 1 THEN 'FILE' WHEN V1.C1 = 28 AND U.PRIV_ALTER_TENANT = 1 THEN 'ALTER TENANT' WHEN V1.C1 = 29 AND U.PRIV_ALTER_SYSTEM = 1 THEN 'ALTER SYSTEM' WHEN V1.C1 = 30 AND U.PRIV_CREATE_RESOURCE_POOL = 1 THEN 'CREATE RESOURCE POOL' WHEN V1.C1 = 31 AND U.PRIV_CREATE_RESOURCE_UNIT = 1 THEN 'CREATE RESOURCE UNIT' WHEN V1.C1 = 33 AND U.PRIV_REPL_SLAVE = 1 THEN 'REPLICATION SLAVE' WHEN V1.C1 = 34 AND U.PRIV_REPL_CLIENT = 1 THEN 'REPLICATION CLIENT' WHEN V1.C1 = 0 AND U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 AND U.PRIV_CREATE_USER = 0 AND U.PRIV_DELETE = 0 AND U.PRIV_DROP = 0 AND U.PRIV_INSERT = 0 AND U.PRIV_UPDATE = 0 AND U.PRIV_SELECT = 0 AND U.PRIV_INDEX = 0 AND U.PRIV_CREATE_VIEW = 0 AND U.PRIV_SHOW_VIEW = 0 AND U.PRIV_SHOW_DB = 0 AND U.PRIV_SUPER = 0 AND U.PRIV_PROCESS = 0 AND U.PRIV_CREATE_SYNONYM = 0 AND U.PRIV_FILE = 0 AND U.PRIV_ALTER_TENANT = 0 AND U.PRIV_ALTER_SYSTEM = 0 AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 AND U.PRIV_REPL_CLIENT = 0 THEN 'USAGE' END PRIVILEGE_TYPE , CASE WHEN U.PRIV_GRANT_OPTION = 0 THEN 'NO' WHEN U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 AND U.PRIV_CREATE_USER = 0 AND U.PRIV_DELETE = 0 AND U.PRIV_DROP = 0 AND U.PRIV_INSERT = 0 AND U.PRIV_UPDATE = 0 AND U.PRIV_SELECT = 0 AND U.PRIV_INDEX = 0 AND U.PRIV_CREATE_VIEW = 0 AND U.PRIV_SHOW_VIEW = 0 AND U.PRIV_SHOW_DB = 0 AND U.PRIV_SUPER = 0 AND U.PRIV_PROCESS = 0 AND U.PRIV_CREATE_SYNONYM = 0 AND U.PRIV_FILE = 0 AND U.PRIV_ALTER_TENANT = 0 AND U.PRIV_ALTER_SYSTEM = 0 AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 AND U.PRIV_REPL_CLIENT = 0 THEN 'NO' WHEN U.PRIV_GRANT_OPTION = 1 THEN 'YES' END IS_GRANTABLE FROM oceanbase.__all_user U, (SELECT 0 AS C1 UNION ALL SELECT 1 AS C1 UNION ALL SELECT 2 AS C1 UNION ALL SELECT 3 AS C1 UNION ALL SELECT 4 AS C1 UNION ALL SELECT 5 AS C1 UNION ALL SELECT 7 AS C1 UNION ALL SELECT 8 AS C1 UNION ALL SELECT 9 AS C1 UNION ALL SELECT 10 AS C1 UNION ALL SELECT 11 AS C1 UNION ALL SELECT 12 AS C1 UNION ALL SELECT 13 AS C1 UNION ALL SELECT 14 AS C1 UNION ALL SELECT 15 AS C1 UNION ALL SELECT 17 AS C1 UNION ALL SELECT 27 AS C1 UNION ALL SELECT 28 AS C1 UNION ALL SELECT 29 AS C1 UNION ALL SELECT 30 AS C1 UNION ALL SELECT 31 AS C1 UNION ALL SELECT 33 AS C1 UNION ALL SELECT 34 AS C1) V1, (SELECT USER_ID FROM oceanbase.__all_user WHERE TENANT_ID = 0 AND CONCAT(USER_NAME, '@', HOST) = CURRENT_USER()) CURR LEFT JOIN (SELECT USER_ID FROM oceanbase.__all_database_privilege WHERE TENANT_ID = 0 AND DATABASE_NAME = 'mysql' AND PRIV_SELECT = 1) DB ON CURR.USER_ID = DB.USER_ID WHERE U.TENANT_ID = 0 AND (DB.USER_ID IS NOT NULL OR 512 & CURRENT_USER_PRIV() = 512 OR U.USER_ID = CURR.USER_ID)) V WHERE V.PRIVILEGE_TYPE IS NOT NULL utf8mb4 utf8mb4_general_ci +USER_PRIVILEGES CREATE VIEW `USER_PRIVILEGES` AS SELECT CAST(CONCAT('''', V.USER_NAME, '''', '@', '''', V.HOST, '''') AS CHAR(81)) AS GRANTEE , CAST('def' AS CHAR(512)) AS TABLE_CATALOG , CAST(V.PRIVILEGE_TYPE AS CHAR(64)) AS PRIVILEGE_TYPE , CAST(V.IS_GRANTABLE AS CHAR(3)) AS IS_GRANTABLE FROM (SELECT U.USER_NAME AS USER_NAME, U.HOST AS HOST, CASE WHEN V1.C1 = 1 AND U.PRIV_ALTER = 1 THEN 'ALTER' WHEN V1.C1 = 2 AND U.PRIV_CREATE = 1 THEN 'CREATE' WHEN V1.C1 = 3 AND U.PRIV_CREATE_USER = 1 THEN 'CREATE USER' WHEN V1.C1 = 4 AND U.PRIV_DELETE = 1 THEN 'DELETE' WHEN V1.C1 = 5 AND U.PRIV_DROP = 1 THEN 'DROP' WHEN V1.C1 = 7 AND U.PRIV_INSERT = 1 THEN 'INSERT' WHEN V1.C1 = 8 AND U.PRIV_UPDATE = 1 THEN 'UPDATE' WHEN V1.C1 = 9 AND U.PRIV_SELECT = 1 THEN 'SELECT' WHEN V1.C1 = 10 AND U.PRIV_INDEX = 1 THEN 'INDEX' WHEN V1.C1 = 11 AND U.PRIV_CREATE_VIEW = 1 THEN 'CREATE VIEW' WHEN V1.C1 = 12 AND U.PRIV_SHOW_VIEW = 1 THEN 'SHOW VIEW' WHEN V1.C1 = 13 AND U.PRIV_SHOW_DB = 1 THEN 'SHOW DB' WHEN V1.C1 = 14 AND U.PRIV_SUPER = 1 THEN 'SUPER' WHEN V1.C1 = 15 AND U.PRIV_PROCESS = 1 THEN 'PROCESS' WHEN V1.C1 = 17 AND U.PRIV_CREATE_SYNONYM = 1 THEN 'CREATE SYNONYM' WHEN V1.C1 = 27 AND U.PRIV_FILE = 1 THEN 'FILE' WHEN V1.C1 = 28 AND U.PRIV_ALTER_TENANT = 1 THEN 'ALTER TENANT' WHEN V1.C1 = 29 AND U.PRIV_ALTER_SYSTEM = 1 THEN 'ALTER SYSTEM' WHEN V1.C1 = 30 AND U.PRIV_CREATE_RESOURCE_POOL = 1 THEN 'CREATE RESOURCE POOL' WHEN V1.C1 = 31 AND U.PRIV_CREATE_RESOURCE_UNIT = 1 THEN 'CREATE RESOURCE UNIT' WHEN V1.C1 = 33 AND U.PRIV_REPL_SLAVE = 1 THEN 'REPLICATION SLAVE' WHEN V1.C1 = 34 AND U.PRIV_REPL_CLIENT = 1 THEN 'REPLICATION CLIENT' WHEN V1.C1 = 35 AND U.PRIV_DROP_DATABASE_LINK = 1 THEN 'DROP DATABASE LINK' WHEN V1.C1 = 36 AND U.PRIV_CREATE_DATABASE_LINK = 1 THEN 'CREATE DATABASE LINK' WHEN V1.C1 = 0 AND U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 AND U.PRIV_CREATE_USER = 0 AND U.PRIV_DELETE = 0 AND U.PRIV_DROP = 0 AND U.PRIV_INSERT = 0 AND U.PRIV_UPDATE = 0 AND U.PRIV_SELECT = 0 AND U.PRIV_INDEX = 0 AND U.PRIV_CREATE_VIEW = 0 AND U.PRIV_SHOW_VIEW = 0 AND U.PRIV_SHOW_DB = 0 AND U.PRIV_SUPER = 0 AND U.PRIV_PROCESS = 0 AND U.PRIV_CREATE_SYNONYM = 0 AND U.PRIV_FILE = 0 AND U.PRIV_ALTER_TENANT = 0 AND U.PRIV_ALTER_SYSTEM = 0 AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 AND U.PRIV_REPL_CLIENT = 0 AND U.PRIV_DROP_DATABASE_LINK = 0 AND U.PRIV_CREATE_DATABASE_LINK = 0 THEN 'USAGE' END PRIVILEGE_TYPE , CASE WHEN U.PRIV_GRANT_OPTION = 0 THEN 'NO' WHEN U.PRIV_ALTER = 0 AND U.PRIV_CREATE = 0 AND U.PRIV_CREATE_USER = 0 AND U.PRIV_DELETE = 0 AND U.PRIV_DROP = 0 AND U.PRIV_INSERT = 0 AND U.PRIV_UPDATE = 0 AND U.PRIV_SELECT = 0 AND U.PRIV_INDEX = 0 AND U.PRIV_CREATE_VIEW = 0 AND U.PRIV_SHOW_VIEW = 0 AND U.PRIV_SHOW_DB = 0 AND U.PRIV_SUPER = 0 AND U.PRIV_PROCESS = 0 AND U.PRIV_CREATE_SYNONYM = 0 AND U.PRIV_FILE = 0 AND U.PRIV_ALTER_TENANT = 0 AND U.PRIV_ALTER_SYSTEM = 0 AND U.PRIV_CREATE_RESOURCE_POOL = 0 AND U.PRIV_CREATE_RESOURCE_UNIT = 0 AND U.PRIV_REPL_SLAVE = 0 AND U.PRIV_REPL_CLIENT = 0 AND U.PRIV_DROP_DATABASE_LINK = 0 AND U.PRIV_CREATE_DATABASE_LINK = 0 THEN 'NO' WHEN U.PRIV_GRANT_OPTION = 1 THEN 'YES' END IS_GRANTABLE FROM oceanbase.__all_user U, (SELECT 0 AS C1 UNION ALL SELECT 1 AS C1 UNION ALL SELECT 2 AS C1 UNION ALL SELECT 3 AS C1 UNION ALL SELECT 4 AS C1 UNION ALL SELECT 5 AS C1 UNION ALL SELECT 7 AS C1 UNION ALL SELECT 8 AS C1 UNION ALL SELECT 9 AS C1 UNION ALL SELECT 10 AS C1 UNION ALL SELECT 11 AS C1 UNION ALL SELECT 12 AS C1 UNION ALL SELECT 13 AS C1 UNION ALL SELECT 14 AS C1 UNION ALL SELECT 15 AS C1 UNION ALL SELECT 17 AS C1 UNION ALL SELECT 27 AS C1 UNION ALL SELECT 28 AS C1 UNION ALL SELECT 29 AS C1 UNION ALL SELECT 30 AS C1 UNION ALL SELECT 31 AS C1 UNION ALL SELECT 33 AS C1 UNION ALL SELECT 34 AS C1 UNION ALL SELECT 35 AS C1 UNION ALL SELECT 36 AS C1) V1, (SELECT USER_ID FROM oceanbase.__all_user WHERE TENANT_ID = 0 AND CONCAT(USER_NAME, '@', HOST) = CURRENT_USER()) CURR LEFT JOIN (SELECT USER_ID FROM oceanbase.__all_database_privilege WHERE TENANT_ID = 0 AND DATABASE_NAME = 'mysql' AND PRIV_SELECT = 1) DB ON CURR.USER_ID = DB.USER_ID WHERE U.TENANT_ID = 0 AND (DB.USER_ID IS NOT NULL OR 512 & CURRENT_USER_PRIV() = 512 OR U.USER_ID = CURR.USER_ID)) V WHERE V.PRIVILEGE_TYPE IS NOT NULL utf8mb4 utf8mb4_general_ci desc information_schema.user_privileges; Field Type Null Key Default Extra GRANTEE varchar(81) NO @@ -60,6 +60,8 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE 'root'@'%' def CREATE RESOURCE UNIT YES 'root'@'%' def REPLICATION SLAVE YES 'root'@'%' def REPLICATION CLIENT YES +'root'@'%' def DROP DATABASE LINK YES +'root'@'%' def CREATE DATABASE LINK YES 'admin'@'%' def ALTER YES 'admin'@'%' def CREATE YES 'admin'@'%' def CREATE USER YES @@ -82,3 +84,5 @@ GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE 'admin'@'%' def CREATE RESOURCE UNIT YES 'admin'@'%' def REPLICATION SLAVE YES 'admin'@'%' def REPLICATION CLIENT YES +'admin'@'%' def DROP DATABASE LINK YES +'admin'@'%' def CREATE DATABASE LINK YES diff --git a/unittest/sql/parser/test_parser.result b/unittest/sql/parser/test_parser.result index f714888ab6..a272f2c97f 100644 --- a/unittest/sql/parser/test_parser.result +++ b/unittest/sql/parser/test_parser.result @@ -27,7 +27,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { @@ -106,7 +107,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { @@ -185,7 +187,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":4, "str_val":"s002" - } + }, + { } ] }, { @@ -366,7 +369,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":4, "str_val":"s001" - } + }, + { } ] }, { @@ -547,7 +551,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":4, "str_val":"s001" - } + }, + { } ] }, { @@ -1376,7 +1381,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -1779,7 +1785,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -2157,7 +2164,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -2448,7 +2456,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -2552,7 +2561,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -2651,7 +2661,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -2781,7 +2792,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -2921,7 +2933,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -3056,7 +3069,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -3323,7 +3337,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -3577,7 +3592,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -3838,7 +3854,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -3869,7 +3886,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -4132,7 +4150,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -4158,7 +4177,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -4416,7 +4436,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -4442,7 +4463,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -4605,7 +4627,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -4859,7 +4882,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -5102,7 +5126,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":8, "str_val":"rongxuan" - } + }, + { } ] }, { @@ -5226,7 +5251,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":8, "str_val":"rongxuan" - } + }, + { } ] }, { @@ -5355,7 +5381,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":8, "str_val":"rongxuan" - } + }, + { } ] }, { @@ -5495,7 +5522,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] } ] @@ -5544,7 +5572,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":1, "str_val":"t" - } + }, + { } ] }, { @@ -5559,7 +5588,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] } ] @@ -5595,7 +5625,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":8, "str_val":"rongxuan" - } + }, + { } ] }, { @@ -5686,7 +5717,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":8, "str_val":"rongxuan" - } + }, + { } ] }, { @@ -5782,7 +5814,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":8, "str_val":"rongxuan" - } + }, + { } ] }, { @@ -6061,7 +6094,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -6172,7 +6206,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -6267,7 +6302,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -6445,7 +6481,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -6668,7 +6705,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -6940,7 +6978,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":1, "str_val":"e" - } + }, + { } ] }, { }, @@ -6966,7 +7005,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":6, "str_val":"stores" - } + }, + { } ] }, { }, @@ -7066,7 +7106,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":11, "str_val":"departments" - } + }, + { } ] }, { }, @@ -8405,7 +8446,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -8514,7 +8556,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -8674,7 +8717,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -8783,7 +8827,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -8943,7 +8988,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -9052,7 +9098,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -9212,7 +9259,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -9315,7 +9363,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -9473,7 +9522,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -9582,7 +9632,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -9742,7 +9793,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -9851,7 +9903,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -10011,7 +10064,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -10120,7 +10174,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -10280,7 +10335,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -10383,7 +10439,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -10541,7 +10598,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -10650,7 +10708,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -10810,7 +10869,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -10919,7 +10979,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -11079,7 +11140,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -11188,7 +11250,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -11348,7 +11411,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -11451,7 +11515,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -11609,7 +11674,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -11718,7 +11784,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -11878,7 +11945,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -11987,7 +12055,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -12147,7 +12216,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -12256,7 +12326,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -12416,7 +12487,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -12519,7 +12591,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -12677,7 +12750,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -12786,7 +12860,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -12946,7 +13021,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -13055,7 +13131,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -13215,7 +13292,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -13324,7 +13402,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -13484,7 +13563,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -13587,7 +13667,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -13745,7 +13826,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -13854,7 +13936,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -14014,7 +14097,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -14123,7 +14207,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -14283,7 +14368,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -14392,7 +14478,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -14552,7 +14639,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -14655,7 +14743,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -14813,7 +14902,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -14916,7 +15006,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -15074,7 +15165,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -15177,7 +15269,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -15335,7 +15428,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -15422,7 +15516,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -15580,7 +15675,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -15673,7 +15769,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -15833,7 +15930,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -15920,7 +16018,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -16015,7 +16114,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -16135,7 +16235,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -16222,7 +16323,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -16317,7 +16419,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -16437,7 +16540,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -16540,7 +16644,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -16660,7 +16765,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -16811,7 +16917,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -16931,7 +17038,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -17082,7 +17190,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -17461,7 +17570,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -17660,7 +17770,8 @@ question_mask_size: 1 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -17794,7 +17905,8 @@ question_mask_size: 1 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -17928,7 +18040,8 @@ question_mask_size: 2 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -18015,7 +18128,8 @@ question_mask_size: 2 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -18148,7 +18262,8 @@ question_mask_size: 2 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -18318,7 +18433,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -18344,7 +18460,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -18456,7 +18573,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -18482,7 +18600,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -18594,7 +18713,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -18620,7 +18740,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -18744,7 +18865,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -18770,7 +18892,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] }, { }, @@ -18800,7 +18923,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t3" - } + }, + { } ] }, { }, @@ -19009,7 +19133,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":4, "str_val":"test" - } + }, + { } ] }, { @@ -19119,7 +19244,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":4, "str_val":"test" - } + }, + { } ] }, { }, @@ -19218,7 +19344,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":4, "str_val":"test" - } + }, + { } ] }, { }, @@ -19322,7 +19449,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":4, "str_val":"test" - } + }, + { } ] }, { }, @@ -19426,7 +19554,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":4, "str_val":"test" - } + }, + { } ] }, { }, @@ -19638,7 +19767,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -19770,7 +19900,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -19897,7 +20028,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -20024,7 +20156,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -20151,7 +20284,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -20236,7 +20370,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -20362,7 +20497,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -20447,7 +20583,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -20554,7 +20691,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -20642,7 +20780,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -20725,7 +20864,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":8, "str_val":"out_name" - } + }, + { } ] } ] @@ -20764,7 +20904,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":8, "str_val":"out_name" - } + }, + { } ] } ] @@ -21586,7 +21727,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -21687,7 +21829,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -21886,7 +22029,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -22043,7 +22187,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -22201,7 +22346,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -22359,7 +22505,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -22432,7 +22579,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { @@ -22447,7 +22595,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t2" - } + }, + { } ] } ] @@ -22501,7 +22650,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, { }, @@ -22578,7 +22728,8 @@ question_mask_size: 0 "int_val":9223372036854775807, "str_len":2, "str_val":"t1" - } + }, + { } ] }, {