602 lines
28 KiB
C++
602 lines
28 KiB
C++
/**
|
|
* 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 <utility>
|
|
#include "sql/engine/cmd/ob_get_diagnostics_executor.h"
|
|
#include "sql/resolver/cmd/ob_get_diagnostics_stmt.h"
|
|
#include "observer/ob_inner_sql_connection_pool.h"
|
|
#include "observer/ob_inner_sql_connection.h"
|
|
#include "observer/ob_inner_sql_result.h"
|
|
#include "share/ob_define.h"
|
|
#include "sql/session/ob_session_val_map.h"
|
|
#include "pl/ob_pl.h"
|
|
#include "share/ob_lob_access_utils.h"
|
|
using namespace oceanbase::common;
|
|
using namespace oceanbase::share;
|
|
using namespace oceanbase::share::schema;
|
|
namespace oceanbase
|
|
{
|
|
namespace sql
|
|
{
|
|
|
|
#define SET_OBJ_VAR(expect_type, integer_val, str_val, has_lob_header) do { \
|
|
ObObj obj; \
|
|
if (ObTinyIntType == expect_type) { \
|
|
obj.set_tinyint(integer_val); \
|
|
} else if (ObSmallIntType == expect_type) { \
|
|
obj.set_smallint(integer_val); \
|
|
} else if (ObMediumIntType == expect_type) { \
|
|
obj.set_mediumint(integer_val); \
|
|
} else if (ObInt32Type == expect_type) { \
|
|
obj.set_int32(integer_val); \
|
|
} else if (ObIntType == expect_type) { \
|
|
obj.set_int(integer_val); \
|
|
} else if (ObUTinyIntType == expect_type) { \
|
|
obj.set_utinyint(integer_val); \
|
|
} else if (ObUSmallIntType == expect_type) { \
|
|
obj.set_usmallint(integer_val); \
|
|
} else if (ObUMediumIntType == expect_type) { \
|
|
obj.set_umediumint(integer_val); \
|
|
} else if (ObUInt32Type == expect_type) { \
|
|
obj.set_uint32(integer_val); \
|
|
} else if (ObUInt64Type == expect_type) { \
|
|
obj.set_uint64(integer_val); \
|
|
} else if (ObFloatType == expect_type) { \
|
|
obj.set_float(integer_val); \
|
|
} else if (ObDoubleType == expect_type) { \
|
|
obj.set_double(integer_val); \
|
|
} else if (ObUFloatType == expect_type) { \
|
|
obj.set_ufloat(integer_val); \
|
|
} else if (ObUDoubleType == expect_type) { \
|
|
obj.set_udouble(integer_val); \
|
|
} else if (ObNumberType == expect_type) { \
|
|
number::ObNumber num; \
|
|
num.from(integer_val, ctx.get_allocator()); \
|
|
obj.set_number(num); \
|
|
} else if (ObUNumberType == expect_type) { \
|
|
number::ObNumber num; \
|
|
num.from(integer_val, ctx.get_allocator()); \
|
|
obj.set_unumber(num); \
|
|
} else if (ObVarcharType == expect_type) { \
|
|
obj.set_varchar(str_val); \
|
|
obj.set_collation_level(CS_LEVEL_COERCIBLE); \
|
|
obj.set_collation_type(collation_type); \
|
|
} else if (ObCharType == expect_type) { \
|
|
obj.set_char(str_val); \
|
|
obj.set_collation_level(CS_LEVEL_COERCIBLE); \
|
|
obj.set_collation_type(collation_type); \
|
|
} else if (ObTinyTextType == expect_type || \
|
|
ObTextType == expect_type || \
|
|
ObMediumTextType == expect_type || \
|
|
ObLongTextType == expect_type || \
|
|
ObJsonType == expect_type) { \
|
|
ObTextStringResult lob(expect_type, has_lob_header, &ctx.get_allocator()); \
|
|
if (OB_FAIL(lob.init(str_val.length()))) { \
|
|
LOG_WARN("fail to init lob", K(ret), K(lob)); \
|
|
} else if (OB_FAIL(lob.append(str_val))) { \
|
|
LOG_WARN("fail to append str", K(ret), K(lob), K(str_val)); \
|
|
} else { \
|
|
ObString lob_str; \
|
|
lob.get_result_buffer(lob_str); \
|
|
obj.set_string(expect_type, lob_str); \
|
|
obj.set_collation_level(CS_LEVEL_COERCIBLE); \
|
|
obj.set_collation_type(collation_type); \
|
|
if (lob.has_lob_header()) { \
|
|
obj.set_has_lob_header(); \
|
|
} \
|
|
} \
|
|
} else { \
|
|
ret = OB_NOT_SUPPORTED; \
|
|
LOG_USER_ERROR(OB_NOT_SUPPORTED, "not supported pl var type"); \
|
|
} \
|
|
if (OB_SUCC(ret)) { \
|
|
ObObjParam value(obj); \
|
|
value.set_param_meta(); \
|
|
result = value; \
|
|
} \
|
|
} while (0)
|
|
|
|
ObGetDiagnosticsExecutor::ObGetDiagnosticsExecutor() {}
|
|
|
|
ObGetDiagnosticsExecutor::~ObGetDiagnosticsExecutor() {}
|
|
|
|
int ObGetDiagnosticsExecutor::assign_condition_val(ObExecContext &ctx, ObGetDiagnosticsStmt &stmt,
|
|
ObSQLSessionInfo *session_info,
|
|
sqlclient::ObISQLConnection *conn,
|
|
int64_t err_ret, ObString err_msg_c, ObString sql_state_c)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
CK (OB_NOT_NULL(session_info));
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < stmt.get_info_argument().count(); ++i) {
|
|
int64_t affected_rows = 0;
|
|
ObString var;
|
|
ObSqlString set_sql;
|
|
const ObString &val = stmt.get_info_argument().at(i);
|
|
const ObRawExpr* var_expr = stmt.get_params().at(i + 1);
|
|
CK (OB_NOT_NULL(var_expr));
|
|
if (OB_FAIL(ret)) {
|
|
} else if (T_OP_GET_USER_VAR == var_expr->get_expr_type()) {
|
|
const ObSysFunRawExpr *func_expr = static_cast<const ObSysFunRawExpr*>(var_expr);
|
|
if (OB_ISNULL(func_expr->get_param_expr(0))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("sys var is NULL", K(*func_expr), K(ret));
|
|
} else if (OB_UNLIKELY(!func_expr->get_param_expr(0)->is_const_raw_expr()
|
|
|| !static_cast<const ObConstRawExpr*>(func_expr->get_param_expr(0))->get_value().is_varchar())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid sys var", K(*func_expr->get_param_expr(0)), K(ret));
|
|
} else {
|
|
var = static_cast<const ObConstRawExpr*>(func_expr->get_param_expr(0))->get_value().get_varchar();
|
|
}
|
|
|
|
DIAG_INFO_TYPE info_type;
|
|
OZ (stmt.get_diag_info_type_by_name(val, info_type));
|
|
if (OB_SUCC(ret)) {
|
|
switch (info_type) {
|
|
case MYSQL_ERRNO_TYPE:
|
|
OZ(set_sql.assign_fmt("set %s%s=\"%d\";", "@", var.ptr(), ob_errpkt_errno(err_ret, lib::is_oracle_mode())));
|
|
break;
|
|
case MESSAGE_TEXT_TYPE:
|
|
OZ(set_sql.assign_fmt("set %s%s=\"%s\";", "@", var.ptr(), err_msg_c.ptr()));
|
|
break;
|
|
case RETURNED_SQLSTATE_TYPE:
|
|
OZ(set_sql.assign_fmt("set %s%s=\"%s\";", "@", var.ptr(),
|
|
err_ret > 0 ? sql_state_c.ptr() : ob_sqlstate(err_ret)));
|
|
break;
|
|
case CLASS_ORIGIN_TYPE:
|
|
case SUBCLASS_ORIGIN_TYPE:
|
|
OZ(set_sql.assign_fmt("set %s%s=\"%s\";", "@", var.ptr(), "ISO 9075"));
|
|
break;
|
|
case TABLE_NAME_TYPE:
|
|
case COLUMN_NAME_TYPE:
|
|
case CONSTRAINT_CATALOG_TYPE:
|
|
case CONSTRAINT_SCHEMA_TYPE:
|
|
case CONSTRAINT_NAME_TYPE:
|
|
case CATALOG_NAME_TYPE:
|
|
case SCHEMA_NAME_TYPE:
|
|
case CURSOR_NAME_TYPE:
|
|
/* do nothing */
|
|
break;
|
|
default:
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected type", K(ret), K(info_type));
|
|
break;
|
|
}
|
|
}
|
|
|
|
CK (OB_NOT_NULL(conn));
|
|
if (OB_SUCC(ret) && set_sql.length() != 0) {
|
|
if (OB_FAIL(conn->execute_write(session_info->get_effective_tenant_id(), set_sql.ptr(), affected_rows))) {
|
|
LOG_WARN("execute write failed", K(ret), K(set_sql), K(affected_rows));
|
|
}
|
|
}
|
|
} else if (OB_LIKELY(var_expr->is_const_raw_expr())) {
|
|
const ObConstRawExpr *const_expr = static_cast<const ObConstRawExpr *>(var_expr);
|
|
if (T_QUESTIONMARK == const_expr->get_expr_type()) {
|
|
ObCollationType collation_type;
|
|
ObObjParam result;
|
|
pl::ObPLContext *pl_context = nullptr;
|
|
pl::ObPLExecState *pl_state = nullptr;
|
|
char str[50] = {0};
|
|
CK (OB_NOT_NULL(pl_context = session_info->get_pl_context()));
|
|
CK (OB_NOT_NULL(pl_state = pl_context->get_current_state()));
|
|
OZ (session_info->get_collation_connection(collation_type));
|
|
DIAG_INFO_TYPE info_type;
|
|
OZ (stmt.get_diag_info_type_by_name(val, info_type));
|
|
int64_t idx = const_expr->get_value().get_unknown();
|
|
idx = stmt.get_origin_param_index(idx);
|
|
CK (idx != OB_INVALID_INDEX);
|
|
CK (idx < pl_state->get_function().get_variables().count());
|
|
if (OB_SUCC(ret)) {
|
|
ObObj obj;
|
|
pl::ObPLDataType pl_data_type = pl_state->get_function().get_variables().at(idx);
|
|
CK (nullptr != pl_data_type.get_data_type());
|
|
if (OB_SUCC(ret)) {
|
|
ObObjType expect_type = pl_data_type.get_data_type()->get_obj_type();
|
|
bool has_lob_header = pl_data_type.get_data_type()->get_meta_type().has_lob_header();
|
|
switch (info_type) {
|
|
case MYSQL_ERRNO_TYPE:
|
|
{
|
|
int64_t errnum = ob_errpkt_errno(err_ret, lib::is_oracle_mode());
|
|
sprintf(str, "%ld", errnum);
|
|
SET_OBJ_VAR(expect_type, errnum, ObString(str), has_lob_header);
|
|
}
|
|
break;
|
|
case MESSAGE_TEXT_TYPE:
|
|
{
|
|
SET_OBJ_VAR(expect_type, (int64_t)0, err_msg_c, has_lob_header);
|
|
}
|
|
break;
|
|
case RETURNED_SQLSTATE_TYPE:
|
|
{
|
|
ObString sqlstate(ob_sqlstate(err_ret));
|
|
if (err_ret > 0) {
|
|
SET_OBJ_VAR(expect_type, (int64_t)0, sql_state_c, has_lob_header);
|
|
} else {
|
|
SET_OBJ_VAR(expect_type, (int64_t)0, sqlstate, has_lob_header);
|
|
}
|
|
}
|
|
break;
|
|
case CLASS_ORIGIN_TYPE:
|
|
case SUBCLASS_ORIGIN_TYPE:
|
|
{
|
|
SET_OBJ_VAR(expect_type, (int64_t)0, ObString("ISO 9075"), has_lob_header);
|
|
}
|
|
break;
|
|
case COLUMN_NAME_TYPE:
|
|
case CONSTRAINT_CATALOG_TYPE:
|
|
case CONSTRAINT_SCHEMA_TYPE:
|
|
case CONSTRAINT_NAME_TYPE:
|
|
case CATALOG_NAME_TYPE:
|
|
case SCHEMA_NAME_TYPE:
|
|
case CURSOR_NAME_TYPE:
|
|
/* do nothing */
|
|
break;
|
|
default:
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected type", K(ret), K(info_type));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
OZ (pl_state->set_var(idx, result));
|
|
}
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected expr type", K(ret));
|
|
}
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected expr type", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObGetDiagnosticsExecutor::get_condition_num(ObExecContext &ctx, ObGetDiagnosticsStmt &stmt, int64_t &num)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObSQLSessionInfo *session_info = ctx.get_my_session();
|
|
pl::ObPLContext *pl_context = nullptr;
|
|
pl::ObPLExecState *pl_state = nullptr;
|
|
const ObRawExpr* cond_argument = nullptr;
|
|
|
|
CK(OB_NOT_NULL(session_info));
|
|
if (0 == stmt.get_params().count()) {
|
|
/* 发生了OB_ERR_BAD_FIELD_ERROR错误,但是语句能够正常执行 */
|
|
ret = OB_ERR_BAD_FIELD_ERROR;
|
|
} else {
|
|
CK (stmt.get_params().count() == stmt.get_info_argument().count() + 1);
|
|
OX (cond_argument = stmt.get_params().at(0));
|
|
CK (OB_NOT_NULL(cond_argument));
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_LIKELY(cond_argument->is_const_raw_expr())) {
|
|
const ObConstRawExpr *const_expr = static_cast<const ObConstRawExpr *>(cond_argument);
|
|
if (T_QUESTIONMARK == const_expr->get_expr_type()) {
|
|
CK (OB_NOT_NULL(pl_context = session_info->get_pl_context()));
|
|
CK (OB_NOT_NULL(pl_state = pl_context->get_current_state()));
|
|
ObObjParam value;
|
|
int64_t idx = const_expr->get_value().get_unknown();
|
|
idx = stmt.get_origin_param_index(idx);
|
|
CK (idx != OB_INVALID_INDEX);
|
|
OZ (pl_state->get_var(idx, value));
|
|
OX (num = value.get_int());
|
|
if (OB_SUCC(ret)) {
|
|
ret = (num <= 0 || num >= MAX_BUFFER_SIZE) ? OB_ERR_INVALID_CONDITION_NUMBER : ret;
|
|
}
|
|
} else if (T_INT == const_expr->get_expr_type() && const_expr->get_value().is_integer_type()) {
|
|
num = const_expr->get_value().get_int();
|
|
if (OB_SUCC(ret)) {
|
|
ret = (num <= 0 || num >= MAX_BUFFER_SIZE) ? OB_ERR_INVALID_CONDITION_NUMBER : ret;
|
|
}
|
|
} else if (T_VARCHAR == cond_argument->get_expr_type()) {
|
|
//to make '12321' string be a number, 'as2da3' string still be a string.
|
|
ObString arg_str = const_expr->get_value().get_string();
|
|
if (arg_str.ptr() == NULL) {
|
|
ret = OB_ERR_INVALID_CONDITION_NUMBER;
|
|
} else {
|
|
int64_t number = strtoll(arg_str.ptr(), NULL, 10);
|
|
if (INT64_MAX == number || number <= 0 || number >= MAX_BUFFER_SIZE) {
|
|
ret = OB_ERR_INVALID_CONDITION_NUMBER;
|
|
} else {
|
|
num = number;
|
|
}
|
|
}
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("condition argument is invalid", K(ret));
|
|
}
|
|
} else if (T_OP_GET_USER_VAR == cond_argument->get_expr_type()) {
|
|
const ObSysFunRawExpr *func_expr = static_cast<const ObSysFunRawExpr*>(cond_argument);
|
|
if (OB_ISNULL(func_expr->get_param_expr(0))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("sys var is NULL", K(*func_expr), K(ret));
|
|
} else if (OB_UNLIKELY(!func_expr->get_param_expr(0)->is_const_raw_expr()
|
|
|| !static_cast<const ObConstRawExpr*>(func_expr->get_param_expr(0))->get_value().is_varchar())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid sys var", K(*func_expr->get_param_expr(0)), K(ret));
|
|
} else {
|
|
const ObString var_name = static_cast<const ObConstRawExpr*>(func_expr->get_param_expr(0))->get_value().get_varchar();
|
|
ObObj value;
|
|
int64_t number = 0;
|
|
if (OB_FAIL(session_info->get_user_variable_value(var_name, value))) {
|
|
LOG_WARN("get user variable failed", K(var_name), K(ret));
|
|
} else if (value.is_integer_type()) {
|
|
OZ (value.get_int(num));
|
|
} else if (value.is_string_type()) {
|
|
ObString str;
|
|
if (OB_FAIL(value.get_varchar(str))) {
|
|
LOG_WARN("get varchar failed", K(ret));
|
|
} else if (FALSE_IT(number = strtoll(str.ptr(), NULL, 10))) {
|
|
} else if (INT64_MAX == number || number <= 0 || number >= MAX_BUFFER_SIZE) {
|
|
ret = OB_ERR_INVALID_CONDITION_NUMBER;
|
|
} else {
|
|
num = number;
|
|
}
|
|
}
|
|
}
|
|
} else if (T_OP_EXCEPT == cond_argument->get_expr_type()) {
|
|
ret = OB_ERR_USER_VARIABLE_UNKNOWN;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObGetDiagnosticsExecutor::execute(ObExecContext &ctx, ObGetDiagnosticsStmt &stmt) {
|
|
int ret = OB_SUCCESS;
|
|
ObSQLSessionInfo *session_info = ctx.get_my_session();
|
|
ObPhysicalPlanCtx *plan_ctx = ctx.get_physical_plan_ctx();
|
|
sqlclient::ObISQLConnection *conn = NULL;
|
|
observer::ObInnerSQLConnectionPool *pool = NULL;
|
|
ObMySQLProxy *sql_proxy = ctx.get_sql_proxy();
|
|
uint64_t tenant_id = 0;
|
|
int64_t warning_count = 0;
|
|
ObSqlString query_virtual;
|
|
if (OB_ISNULL(session_info)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid args", K(ret), KP(session_info));
|
|
} else if (OB_ISNULL(sql_proxy = GCTX.sql_proxy_) || OB_ISNULL(sql_proxy->get_pool())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("sql proxy must not null", K(ret), KP(GCTX.sql_proxy_));
|
|
} else if (OB_UNLIKELY(sqlclient::INNER_POOL != sql_proxy->get_pool()->get_type())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("pool type must be inner", K(ret), "type", sql_proxy->get_pool()->get_type());
|
|
} else if (OB_ISNULL(pool = static_cast<observer::ObInnerSQLConnectionPool*>(sql_proxy->get_pool()))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("pool must not null", K(ret));
|
|
} else if (OB_FAIL(pool->acquire(session_info, conn))) {
|
|
LOG_WARN("failed to get conn", K(ret));
|
|
} else if (OB_FAIL(query_virtual.assign_fmt("select count(*) from %s.%s",
|
|
OB_SYS_DATABASE_NAME, OB_TENANT_VIRTUAL_WARNING_TNAME))) {
|
|
LOG_WARN("assign format failed", K(ret));
|
|
} else {
|
|
SMART_VAR(ObISQLClient::ReadResult, res) {
|
|
tenant_id = session_info->get_effective_tenant_id();
|
|
common::sqlclient::ObMySQLResult *result = NULL;
|
|
if (OB_FAIL(conn->execute_read(tenant_id, query_virtual.ptr(), res))) {
|
|
LOG_WARN("Failed to spi_query", K(query_virtual), K(ret));
|
|
} else if (OB_ISNULL(result = res.get_result())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("failed to get result", K(ret));
|
|
} else if (OB_SUCC(result->next())) {
|
|
EXTRACT_INT_FIELD_MYSQL(*result, "count(*)", warning_count, int64_t);
|
|
}
|
|
}
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (stmt.get_diagnostics_type() == DiagnosticsType::GET_CURRENT_COND) {
|
|
int64_t restored_arg;
|
|
OZ (get_condition_num(ctx, stmt, restored_arg));
|
|
if (OB_ERR_INVALID_CONDITION_NUMBER == ret) {
|
|
ret = OB_SUCCESS;
|
|
LOG_USER_WARN(OB_ERR_INVALID_CONDITION_NUMBER);
|
|
} else if (OB_ERR_USER_VARIABLE_UNKNOWN == ret || OB_OBJ_TYPE_ERROR == ret) {
|
|
ret = OB_SUCCESS;
|
|
LOG_TRACE("condition num is invalid");
|
|
LOG_USER_WARN(OB_ERR_INVALID_CONDITION_NUMBER);
|
|
} else if (OB_ERR_BAD_FIELD_ERROR == ret) {
|
|
ret = OB_SUCCESS;
|
|
ObString scope_name = ObString::make_string("field_list");
|
|
ObString invalid_condition_name = stmt.get_invalid_condition_name();
|
|
LOG_USER_WARN(OB_ERR_BAD_FIELD_ERROR,
|
|
invalid_condition_name.length(), invalid_condition_name.ptr(),
|
|
static_cast<int32_t>(scope_name.length()), scope_name.ptr());
|
|
} else if (OB_FAIL(ret)) {
|
|
LOG_WARN("unexpected error", K(ret));
|
|
} else if (warning_count < restored_arg || restored_arg < 1) {
|
|
LOG_TRACE("condition num is invalid");
|
|
LOG_USER_WARN(OB_ERR_INVALID_CONDITION_NUMBER);
|
|
} else {
|
|
int err_ret;
|
|
ObString err_msg, err_msg_c, sqlstate, sqlstate_c;
|
|
ObSqlString query_virtual;
|
|
if (OB_FAIL(query_virtual.assign_fmt(
|
|
"select message, ori_code, sql_state from %s.%s limit %ld, 1",
|
|
OB_SYS_DATABASE_NAME, OB_TENANT_VIRTUAL_WARNING_TNAME, restored_arg - 1))) {
|
|
LOG_WARN("assign fmt failed", K(ret));
|
|
} else {
|
|
SMART_VAR(ObISQLClient::ReadResult, res) {
|
|
common::sqlclient::ObMySQLResult *result = NULL;
|
|
if (OB_FAIL(conn->execute_read(tenant_id, query_virtual.ptr(), res))) {
|
|
LOG_WARN("Failed to spi_query", K(query_virtual), K(ret));
|
|
} else if (OB_ISNULL(result = res.get_result())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("failed to get result", K(ret));
|
|
} else if (OB_SUCC(result->next())) {
|
|
EXTRACT_VARCHAR_FIELD_MYSQL(*result, "message", err_msg);
|
|
EXTRACT_INT_FIELD_MYSQL(*result, "ori_code", err_ret, int);
|
|
EXTRACT_VARCHAR_FIELD_MYSQL(*result, "sql_state", sqlstate);
|
|
if (OB_FAIL(ret)) {
|
|
} else if (OB_FAIL(ob_write_string(ctx.get_allocator(), err_msg, err_msg_c, true))) {
|
|
//when using ptr(), char *'s end should be '\0'
|
|
LOG_WARN("ob write string failed", K(ret));
|
|
} else if (OB_FAIL(ob_write_string(ctx.get_allocator(), sqlstate, sqlstate_c, true))) {
|
|
//when using ptr(), char *'s end should be '\0'
|
|
LOG_WARN("ob write string failed", K(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
OZ (assign_condition_val(ctx, stmt, session_info, conn, err_ret, err_msg_c, sqlstate_c));
|
|
}
|
|
} else if (stmt.get_diagnostics_type() == DiagnosticsType::GET_STACKED_COND) {
|
|
int64_t restored_arg = 0;
|
|
OZ (get_condition_num(ctx, stmt, restored_arg));
|
|
if (OB_ERR_INVALID_CONDITION_NUMBER == ret) {
|
|
ret = OB_SUCCESS;
|
|
LOG_USER_WARN(OB_ERR_INVALID_CONDITION_NUMBER);
|
|
} else if (OB_ERR_USER_VARIABLE_UNKNOWN == ret || OB_OBJ_TYPE_ERROR == ret) {
|
|
ret = OB_SUCCESS;
|
|
LOG_TRACE("condition num is invalid");
|
|
LOG_USER_WARN(OB_ERR_INVALID_CONDITION_NUMBER);
|
|
} else if (OB_ERR_BAD_FIELD_ERROR == ret) {
|
|
ret = OB_SUCCESS;
|
|
ObString scope_name = ObString::make_string("field_list");
|
|
ObString invalid_condition_name = stmt.get_invalid_condition_name();
|
|
LOG_USER_WARN(OB_ERR_BAD_FIELD_ERROR,
|
|
invalid_condition_name.length(), invalid_condition_name.ptr(),
|
|
static_cast<int32_t>(scope_name.length()), scope_name.ptr());
|
|
} else if (OB_FAIL(ret)) {
|
|
LOG_WARN("unexpected error", K(ret));
|
|
} else if (restored_arg > 1) { /* todo:hr-当前stack诊断区只支持存一条信息 */
|
|
LOG_TRACE("type ok but out of range", K(restored_arg));
|
|
LOG_USER_WARN(OB_ERR_INVALID_CONDITION_NUMBER);
|
|
} else {
|
|
int err_ret;
|
|
int mysql_errcode;
|
|
ObString err_msg_c, sqlstate_c;
|
|
pl::ObPLSqlCodeInfo *sqlcode_info = NULL;
|
|
int64_t idx;
|
|
CK (OB_NOT_NULL(session_info->get_pl_sqlcode_info()));
|
|
OX (sqlcode_info = session_info->get_pl_sqlcode_info());
|
|
CK (sqlcode_info->get_stack_warning_buf().count() > 0);
|
|
OX (idx = sqlcode_info->get_stack_warning_buf().count() - 1);
|
|
if (OB_SUCC(ret)) {
|
|
err_ret = sqlcode_info->get_stack_warning_buf().at(idx).get_err_code();
|
|
err_msg_c = sqlcode_info->get_stack_warning_buf().at(idx).get_err_msg();
|
|
sqlstate_c = sqlcode_info->get_stack_warning_buf().at(idx).get_sql_state();
|
|
}
|
|
OZ (assign_condition_val(ctx, stmt, session_info, conn, err_ret, err_msg_c, sqlstate_c));
|
|
}
|
|
} else if (stmt.get_diagnostics_type() == DiagnosticsType::GET_CURRENT_INFO ||
|
|
stmt.get_diagnostics_type() == DiagnosticsType::GET_STACKED_INFO) {
|
|
CK (stmt.get_params().count() == stmt.get_info_argument().count());
|
|
int64_t old_affected_rows = session_info->get_affected_rows();
|
|
int64_t number;
|
|
if (stmt.get_diagnostics_type() == DiagnosticsType::GET_CURRENT_INFO) {
|
|
number = warning_count;
|
|
} else {
|
|
int64_t idx;
|
|
pl::ObPLSqlCodeInfo *sqlcode_info = NULL;
|
|
CK (OB_NOT_NULL(session_info->get_pl_sqlcode_info()));
|
|
OX (sqlcode_info = session_info->get_pl_sqlcode_info());
|
|
CK (sqlcode_info->get_stack_warning_buf().count() > 0);
|
|
OX (idx = sqlcode_info->get_stack_warning_buf().count() - 1);
|
|
OX (number = 1 + sqlcode_info->get_stack_warning_buf().at(idx).get_readable_warning_count());
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < stmt.get_info_argument().count(); ++i) {
|
|
ObString var;
|
|
const ObString &val = stmt.get_info_argument().at(i);
|
|
int64_t affected_rows = 0;
|
|
ObSqlString set_sql;
|
|
const ObRawExpr* var_expr = stmt.get_params().at(i);
|
|
CK (OB_NOT_NULL(var_expr));
|
|
if (OB_FAIL(ret)) {
|
|
} else if (T_OP_GET_USER_VAR == var_expr->get_expr_type()) {
|
|
const ObSysFunRawExpr *func_expr = static_cast<const ObSysFunRawExpr*>(var_expr);
|
|
if (OB_ISNULL(func_expr->get_param_expr(0))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("sys var is NULL", K(*func_expr), K(ret));
|
|
} else if (OB_UNLIKELY(!func_expr->get_param_expr(0)->is_const_raw_expr()
|
|
|| !static_cast<const ObConstRawExpr*>(func_expr->get_param_expr(0))->get_value().is_varchar())) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("invalid sys var", K(*func_expr->get_param_expr(0)), K(ret));
|
|
} else {
|
|
var = static_cast<const ObConstRawExpr*>(func_expr->get_param_expr(0))->get_value().get_varchar();
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
} else if (val == "NUMBER") {
|
|
if (OB_FAIL(set_sql.assign_fmt("set %s%s=%ld;", "@", var.ptr(), number))) {
|
|
LOG_WARN("assign fmt failed", K(ret));
|
|
}
|
|
} else if (val == "ROW_COUNT") {
|
|
if (OB_FAIL(set_sql.assign_fmt("set %s%s=%ld;", "@", var.ptr(), old_affected_rows))) {
|
|
LOG_WARN("assign fmt failed", K(ret));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (OB_FAIL(conn->execute_write(tenant_id, set_sql.ptr(), affected_rows))) {
|
|
LOG_WARN("execute write failed", K(ret), K(set_sql), K(affected_rows));
|
|
}
|
|
}
|
|
} else if (OB_LIKELY(var_expr->is_const_raw_expr())) {
|
|
const ObConstRawExpr *const_expr = static_cast<const ObConstRawExpr *>(var_expr);
|
|
if (T_QUESTIONMARK == const_expr->get_expr_type()) {
|
|
pl::ObPLContext *pl_context = NULL;
|
|
pl::ObPLExecState *pl_state = NULL;
|
|
CK (OB_NOT_NULL(pl_context = session_info->get_pl_context()));
|
|
CK (OB_NOT_NULL(pl_state = pl_context->get_current_state()));
|
|
|
|
ObObjParam result;
|
|
ObObjParam origin_obj;
|
|
ObCollationType collation_type;
|
|
char str[50] = {0};
|
|
int64_t idx = const_expr->get_value().get_unknown();
|
|
idx = stmt.get_origin_param_index(idx);
|
|
CK (idx != OB_INVALID_INDEX);
|
|
CK (idx < pl_state->get_function().get_variables().count());
|
|
OZ (session_info->get_collation_connection(collation_type));
|
|
if (OB_SUCC(ret)) {
|
|
pl::ObPLDataType pl_data_type = pl_state->get_function().get_variables().at(idx);
|
|
CK (nullptr != pl_data_type.get_data_type());
|
|
if (OB_SUCC(ret)) {
|
|
ObObjType expect_type = pl_data_type.get_data_type()->get_obj_type();
|
|
bool has_lob_header = pl_data_type.get_data_type()->get_meta_type().has_lob_header();
|
|
if (val == "NUMBER") {
|
|
sprintf(str, "%ld", number);
|
|
SET_OBJ_VAR(expect_type, number, ObString(str), has_lob_header);
|
|
} else if (val == "ROW_COUNT") {
|
|
sprintf(str, "%ld", old_affected_rows);
|
|
SET_OBJ_VAR(expect_type, old_affected_rows, ObString(str), has_lob_header);
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected", K(val), K(ret));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
OZ (pl_state->set_var(idx, result));
|
|
}
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected expr type", K(ret));
|
|
}
|
|
} else {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("unexpected expr type", K(ret));
|
|
}
|
|
}
|
|
}
|
|
if (OB_FAIL(pool->release(conn, true))) {
|
|
LOG_WARN("release failed", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
#undef SET_OBJ_VAR
|
|
}/* ns sql*/
|
|
}/* ns oceanbase */
|