1315 lines
47 KiB
C++
1315 lines
47 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_RESV
|
|
#include "sql/ob_sql_context.h"
|
|
#include <algorithm>
|
|
#include "lib/container/ob_se_array_iterator.h"
|
|
#include "sql/resolver/dml/ob_sql_hint.h"
|
|
#include "sql/ob_sql_define.h"
|
|
#include "sql/optimizer/ob_log_plan.h"
|
|
#include "share/schema/ob_schema_getter_guard.h"
|
|
|
|
using namespace ::oceanbase::common;
|
|
namespace oceanbase {
|
|
using namespace share::schema;
|
|
namespace sql {
|
|
bool LocationConstraint::operator==(const LocationConstraint& other) const
|
|
{
|
|
return key_ == other.key_ && phy_loc_type_ == other.phy_loc_type_ && constraint_flags_ == other.constraint_flags_;
|
|
}
|
|
|
|
bool LocationConstraint::operator!=(const LocationConstraint& other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
|
|
int LocationConstraint::calc_constraints_inclusion(
|
|
const ObLocationConstraint* left, const ObLocationConstraint* right, InclusionType& inclusion_result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
inclusion_result = NotSubset;
|
|
if (OB_ISNULL(left) || OB_ISNULL(right)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("invalid argument", K(left), K(right));
|
|
} else {
|
|
const ObLocationConstraint *set1 = NULL, *set2 = NULL;
|
|
bool is_subset = true;
|
|
// insure set1.count() >= set2.count()
|
|
if (left->count() >= right->count()) {
|
|
inclusion_result = LeftIsSuperior;
|
|
set1 = left;
|
|
set2 = right;
|
|
} else {
|
|
inclusion_result = RightIsSuperior;
|
|
set1 = right;
|
|
set2 = left;
|
|
}
|
|
|
|
for (int64_t i = 0; is_subset && i < set2->count(); i++) {
|
|
bool detected = false;
|
|
for (int64_t j = 0; !detected && j < set1->count(); j++) {
|
|
if (set2->at(i) == set1->at(j)) {
|
|
detected = true;
|
|
}
|
|
}
|
|
// if the element is not in set1, set1 can not contain all the elements in set2
|
|
if (!detected) {
|
|
is_subset = false;
|
|
}
|
|
}
|
|
if (!is_subset) {
|
|
inclusion_result = NotSubset;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObLocationConstraintContext::calc_constraints_inclusion(
|
|
const ObPwjConstraint* left, const ObPwjConstraint* right, InclusionType& inclusion_result)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
inclusion_result = NotSubset;
|
|
if (OB_ISNULL(left) || OB_ISNULL(right)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected null", K(ret), K(left), K(right));
|
|
} else {
|
|
const ObPwjConstraint *set1 = NULL, *set2 = NULL;
|
|
bool is_subset = true;
|
|
// insure set1.count() >= set2.count()
|
|
if (left->count() >= right->count()) {
|
|
inclusion_result = LeftIsSuperior;
|
|
set1 = left;
|
|
set2 = right;
|
|
} else {
|
|
inclusion_result = RightIsSuperior;
|
|
set1 = right;
|
|
set2 = left;
|
|
}
|
|
|
|
for (int64_t i = 0; is_subset && i < set2->count(); i++) {
|
|
bool detected = false;
|
|
for (int64_t j = 0; !detected && j < set1->count(); j++) {
|
|
if (set2->at(i) == set1->at(j)) {
|
|
detected = true;
|
|
}
|
|
}
|
|
// if the element is not in set1, set1 can not contain all the elements in set2
|
|
if (!detected) {
|
|
is_subset = false;
|
|
}
|
|
}
|
|
if (!is_subset) {
|
|
inclusion_result = NotSubset;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryRetryInfo::init()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_UNLIKELY(inited_)) {
|
|
ret = OB_INIT_TWICE;
|
|
LOG_ERROR("init twice", K(ret));
|
|
} else {
|
|
inited_ = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void ObQueryRetryInfo::reset()
|
|
{
|
|
inited_ = false;
|
|
is_rpc_timeout_ = false;
|
|
invalid_servers_.reset();
|
|
last_query_retry_err_ = OB_SUCCESS;
|
|
}
|
|
|
|
void ObQueryRetryInfo::clear()
|
|
{
|
|
// here cannot set inited_ as false
|
|
is_rpc_timeout_ = false;
|
|
invalid_servers_.reset();
|
|
// last_query_retry_err_ = OB_SUCCESS;
|
|
}
|
|
|
|
void ObQueryRetryInfo::clear_state_before_each_retry()
|
|
{
|
|
is_rpc_timeout_ = false;
|
|
// The accumulated members of successive retry cannot be cleared here, such as invalid_servers_, last_query_retry_err_
|
|
}
|
|
|
|
// Combine retry information,
|
|
// used for the retry information combination of the main thread and the scheduling thread
|
|
int ObQueryRetryInfo::merge(const ObQueryRetryInfo& other)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (other.is_rpc_timeout_) {
|
|
is_rpc_timeout_ = other.is_rpc_timeout_;
|
|
}
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < other.invalid_servers_.count(); ++i) {
|
|
if (OB_FAIL(add_invalid_server_distinctly(other.invalid_servers_.at(i)))) {
|
|
LOG_WARN("fail to add invalid server distinctly",
|
|
K(ret),
|
|
K(i),
|
|
K(other.invalid_servers_.at(i)),
|
|
K(other.invalid_servers_),
|
|
K(invalid_servers_));
|
|
}
|
|
}
|
|
// last_query_retry_err_ will not be modified on the scheduling thread, so don't worry about it here
|
|
return ret;
|
|
}
|
|
|
|
void ObQueryRetryInfo::set_is_rpc_timeout(bool is_rpc_timeout)
|
|
{
|
|
is_rpc_timeout_ = is_rpc_timeout;
|
|
}
|
|
|
|
bool ObQueryRetryInfo::is_rpc_timeout() const
|
|
{
|
|
return is_rpc_timeout_;
|
|
}
|
|
|
|
int ObQueryRetryInfo::add_invalid_server_distinctly(const ObAddr& invalid_server, bool print_info_log /* = false*/)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool is_found = false;
|
|
for (int64_t i = 0; OB_SUCC(ret) && !is_found && i < invalid_servers_.count(); ++i) {
|
|
if (invalid_server == invalid_servers_.at(i)) {
|
|
is_found = true;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && !is_found) {
|
|
if (OB_FAIL(invalid_servers_.push_back(invalid_server))) {
|
|
LOG_WARN("fail to push back invalid server", K(ret), K(invalid_server));
|
|
}
|
|
}
|
|
if (print_info_log) {
|
|
LOG_INFO("add a server to invalid server list", K(ret), K(invalid_server), K(invalid_servers_));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ObSqlCtx::ObSqlCtx()
|
|
: multi_stmt_item_(),
|
|
session_info_(NULL),
|
|
schema_guard_(NULL),
|
|
sql_proxy_(NULL),
|
|
vt_iter_factory_(NULL),
|
|
use_plan_cache_(true),
|
|
plan_cache_hit_(false),
|
|
self_add_plan_(false),
|
|
disable_privilege_check_(PRIV_CHECK_FLAG_NORMAL),
|
|
partition_table_operator_(NULL),
|
|
session_mgr_(NULL),
|
|
part_mgr_(NULL),
|
|
partition_location_cache_(NULL),
|
|
merged_version_(OB_MERGED_VERSION_INIT),
|
|
force_print_trace_(false),
|
|
is_show_trace_stmt_(false),
|
|
retry_times_(OB_INVALID_COUNT),
|
|
exec_type_(InvalidType),
|
|
is_prepare_protocol_(false),
|
|
is_prepare_stage_(false),
|
|
is_dynamic_sql_(false),
|
|
is_dbms_sql_(false),
|
|
is_cursor_(false),
|
|
is_remote_sql_(false),
|
|
is_execute_async_(false),
|
|
statement_id_(common::OB_INVALID_ID),
|
|
stmt_type_(stmt::T_NONE),
|
|
partition_infos_(),
|
|
is_restore_(false),
|
|
// retry_info_(),
|
|
need_late_compile_(false),
|
|
is_bushy_tree_(false),
|
|
all_plan_const_param_constraints_(nullptr),
|
|
all_possible_const_param_constraints_(nullptr),
|
|
all_equal_param_constraints_(nullptr),
|
|
trans_happened_route_(nullptr),
|
|
is_ddl_from_primary_(false),
|
|
cur_stmt_(NULL),
|
|
can_reroute_sql_(false),
|
|
reroute_info_(),
|
|
is_sensitive_(false)
|
|
{
|
|
sql_id_[0] = '\0';
|
|
sql_id_[common::OB_MAX_SQL_ID_LENGTH] = '\0';
|
|
}
|
|
|
|
void ObSqlCtx::reset()
|
|
{
|
|
multi_stmt_item_.reset();
|
|
session_info_ = NULL;
|
|
sql_schema_guard_.reset();
|
|
schema_guard_ = NULL;
|
|
sql_proxy_ = NULL;
|
|
vt_iter_factory_ = NULL;
|
|
use_plan_cache_ = false;
|
|
plan_cache_hit_ = false;
|
|
self_add_plan_ = false;
|
|
disable_privilege_check_ = PRIV_CHECK_FLAG_NORMAL;
|
|
partition_table_operator_ = NULL;
|
|
session_mgr_ = NULL;
|
|
partition_location_cache_ = NULL;
|
|
merged_version_ = OB_MERGED_VERSION_INIT;
|
|
force_print_trace_ = false;
|
|
is_show_trace_stmt_ = false;
|
|
retry_times_ = OB_INVALID_COUNT;
|
|
sql_id_[0] = '\0';
|
|
sql_id_[common::OB_MAX_SQL_ID_LENGTH] = '\0';
|
|
exec_type_ = InvalidType;
|
|
is_prepare_protocol_ = false;
|
|
is_prepare_stage_ = false;
|
|
is_dynamic_sql_ = false;
|
|
is_remote_sql_ = false;
|
|
is_execute_async_ = false;
|
|
is_restore_ = false;
|
|
loc_sensitive_hint_.reset();
|
|
need_late_compile_ = false;
|
|
all_plan_const_param_constraints_ = nullptr;
|
|
all_possible_const_param_constraints_ = nullptr;
|
|
all_equal_param_constraints_ = nullptr;
|
|
trans_happened_route_ = nullptr;
|
|
is_bushy_tree_ = false;
|
|
is_ddl_from_primary_ = false;
|
|
can_reroute_sql_ = false;
|
|
reroute_info_.reset();
|
|
is_sensitive_ = false;
|
|
clear();
|
|
}
|
|
|
|
// release dynamic allocated memory
|
|
void ObSqlCtx::clear()
|
|
{
|
|
cur_stmt_ = NULL;
|
|
acs_index_infos_.reset();
|
|
partition_infos_.reset();
|
|
related_user_var_names_.reset();
|
|
base_constraints_.reset();
|
|
strict_constraints_.reset();
|
|
non_strict_constraints_.reset();
|
|
multi_stmt_rowkey_pos_.reset();
|
|
}
|
|
|
|
void ObSqlSchemaGuard::reset()
|
|
{
|
|
table_schemas_.reset();
|
|
schema_guard_ = NULL;
|
|
allocator_.reset();
|
|
next_link_table_id_ = 1;
|
|
}
|
|
|
|
int ObSqlSchemaGuard::get_table_schema(
|
|
uint64_t dblink_id, const ObString& database_name, const ObString& table_name, const ObTableSchema*& table_schema)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t schema_count = table_schemas_.count();
|
|
table_schema = NULL;
|
|
for (int64_t i = 0; OB_SUCC(ret) && OB_ISNULL(table_schema) && i < schema_count; i++) {
|
|
const ObTableSchema* tmp_schema = table_schemas_.at(i);
|
|
OV(OB_NOT_NULL(tmp_schema));
|
|
if (OB_SUCC(ret) && dblink_id == tmp_schema->get_dblink_id() &&
|
|
0 == database_name.compare(tmp_schema->get_link_database_name()) &&
|
|
0 == table_name.compare(tmp_schema->get_table_name_str())) {
|
|
table_schema = tmp_schema;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && OB_ISNULL(table_schema)) {
|
|
ObTableSchema* tmp_schema = NULL;
|
|
OV(OB_NOT_NULL(schema_guard_), OB_NOT_INIT);
|
|
OZ(schema_guard_->get_link_table_schema(dblink_id, database_name, table_name, allocator_, tmp_schema));
|
|
OV(OB_NOT_NULL(tmp_schema));
|
|
OX(tmp_schema->set_link_table_id(tmp_schema->get_table_id()));
|
|
OX(tmp_schema->set_table_id(combine_link_table_id(dblink_id, next_link_table_id_++)));
|
|
OV(tmp_schema->get_table_id() != OB_INVALID_ID, OB_ERR_UNEXPECTED, dblink_id, next_link_table_id_);
|
|
OZ(table_schemas_.push_back(tmp_schema));
|
|
OX(table_schema = tmp_schema);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlSchemaGuard::get_table_schema(uint64_t table_id, const ObTableSchema*& table_schema) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (is_link_table_id(table_id)) {
|
|
OZ(get_link_table_schema(table_id, table_schema), table_id);
|
|
} else {
|
|
OV(OB_NOT_NULL(schema_guard_));
|
|
OZ(schema_guard_->get_table_schema(table_id, table_schema), table_id);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlSchemaGuard::get_column_schema(
|
|
uint64_t table_id, const ObString& column_name, const ObColumnSchemaV2*& column_schema) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (is_link_table_id(table_id)) {
|
|
OZ(get_link_column_schema(table_id, column_name, column_schema), table_id, column_name);
|
|
} else {
|
|
OV(OB_NOT_NULL(schema_guard_));
|
|
OZ(schema_guard_->get_column_schema(table_id, column_name, column_schema), table_id, column_name);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlSchemaGuard::get_column_schema(
|
|
uint64_t table_id, uint64_t column_id, const ObColumnSchemaV2*& column_schema) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (is_link_table_id(table_id)) {
|
|
OZ(get_link_column_schema(table_id, column_id, column_schema), table_id, column_id);
|
|
} else {
|
|
OV(OB_NOT_NULL(schema_guard_));
|
|
OZ(schema_guard_->get_column_schema(table_id, column_id, column_schema), table_id, column_id);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlSchemaGuard::get_table_schema_version(const uint64_t table_id, int64_t& schema_version) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (is_link_table_id(table_id)) {
|
|
const ObTableSchema* table_schema = NULL;
|
|
OZ(get_link_table_schema(table_id, table_schema), table_id);
|
|
OV(OB_NOT_NULL(table_schema), OB_TABLE_NOT_EXIST, table_id);
|
|
OX(schema_version = table_schema->get_schema_version());
|
|
} else {
|
|
OV(OB_NOT_NULL(schema_guard_));
|
|
OZ(schema_guard_->get_table_schema_version(table_id, schema_version), table_id);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlSchemaGuard::get_partition_cnt(uint64_t table_id, int64_t& part_cnt) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (is_link_table_id(table_id)) {
|
|
part_cnt = 1;
|
|
} else {
|
|
OV(OB_NOT_NULL(schema_guard_));
|
|
OZ(schema_guard_->get_partition_cnt(table_id, part_cnt), table_id);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlSchemaGuard::get_can_read_index_array(uint64_t table_id, uint64_t* index_tid_array, int64_t& size,
|
|
bool with_mv, bool with_global_index, bool with_domain_index)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (is_link_table_id(table_id)) {
|
|
size = 0;
|
|
} else {
|
|
OV(OB_NOT_NULL(schema_guard_));
|
|
OZ(schema_guard_->get_can_read_index_array(
|
|
table_id, index_tid_array, size, with_mv, with_global_index, with_domain_index));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlSchemaGuard::get_link_table_schema(uint64_t table_id, const ObTableSchema*& table_schema) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t schema_count = table_schemas_.count();
|
|
const ObTableSchema* tmp_schema = NULL;
|
|
table_schema = NULL;
|
|
for (int64_t i = 0; OB_SUCC(ret) && OB_ISNULL(table_schema) && i < schema_count; i++) {
|
|
OX(tmp_schema = table_schemas_.at(i));
|
|
OV(OB_NOT_NULL(tmp_schema));
|
|
if (OB_SUCC(ret) && table_id == tmp_schema->get_table_id()) {
|
|
table_schema = tmp_schema;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlSchemaGuard::get_link_column_schema(
|
|
uint64_t table_id, const ObString& column_name, const ObColumnSchemaV2*& column_schema) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObTableSchema* table_schema = NULL;
|
|
OZ(get_table_schema(table_id, table_schema), table_id);
|
|
if (OB_NOT_NULL(table_schema)) {
|
|
OX(column_schema = table_schema->get_column_schema(column_name));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlSchemaGuard::get_link_column_schema(
|
|
uint64_t table_id, uint64_t column_id, const ObColumnSchemaV2*& column_schema) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
const ObTableSchema* table_schema = NULL;
|
|
OZ(get_table_schema(table_id, table_schema), table_id);
|
|
if (OB_NOT_NULL(table_schema)) {
|
|
OX(column_schema = table_schema->get_column_schema(column_id));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::add_stmt_id_name(const int64_t stmt_id, const common::ObString& stmt_name, ObStmt* stmt)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool name_dup = false;
|
|
if (stmt_id < 0) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Stmt id is invalid", K(ret), K(stmt_id));
|
|
} else {
|
|
// find name dup and equal id
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < stmt_id_name_map_.count(); ++idx) {
|
|
if (!stmt_name.empty() && 0 == stmt_name.case_compare(stmt_id_name_map_.at(idx).name_)) {
|
|
if (name_dup) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Names in array duplicate", K(ret));
|
|
} else {
|
|
name_dup = true;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret)) {
|
|
if (stmt_id == stmt_id_name_map_.at(idx).id_) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Stmt id in array duplicate", K(ret));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (OB_SUCC(ret)) {
|
|
ObString final_name = name_dup ? ObString::make_empty_string() : stmt_name;
|
|
if (!name_dup && !stmt_name.empty() && OB_FAIL(valid_qb_name_stmt_ids_.push_back(stmt_id))) {
|
|
LOG_WARN("fail to push_back stmt_id", K(ret));
|
|
} else if (OB_FAIL(stmt_id_name_map_.push_back(
|
|
IdNamePair(stmt_id, final_name, ObString::make_empty_string(), stmt->get_stmt_type())))) {
|
|
SQL_LOG(WARN, "Add stmt id, name pair error", K(ret));
|
|
} else if (OB_FAIL(id_stmt_map_.push_back(std::pair<int64_t, ObStmt*>(stmt_id, stmt)))) {
|
|
LOG_WARN("Failed to add id stmt pair", K(ret));
|
|
} else {
|
|
// do nothing
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::generate_stmt_name(ObIAllocator* allocator)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
uint64_t OB_MAX_QB_NAME_LENGTH = 20;
|
|
char buf[OB_MAX_QB_NAME_LENGTH];
|
|
if (OB_ISNULL(allocator)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Allocator should not be NULL", K(ret));
|
|
} else if (stmt_id_name_map_.count() > 0) {
|
|
std::sort(stmt_id_name_map_.begin(), stmt_id_name_map_.end());
|
|
int64_t start_ids[5];
|
|
for (int64_t i = 0; i < 5; ++i) {
|
|
start_ids[i] = 1;
|
|
}
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < stmt_id_name_map_.count(); ++idx) {
|
|
IdNamePair& id_name_pair = stmt_id_name_map_.at(idx);
|
|
if (!id_name_pair.origin_name_.empty()) {
|
|
// do nothing
|
|
} else if (stmt::T_SELECT == id_name_pair.stmt_type_ || stmt::T_INSERT == id_name_pair.stmt_type_ ||
|
|
stmt::T_REPLACE == id_name_pair.stmt_type_ || stmt::T_DELETE == id_name_pair.stmt_type_ ||
|
|
stmt::T_UPDATE == id_name_pair.stmt_type_) {
|
|
int64_t pos = 0;
|
|
int64_t* start_id = NULL;
|
|
if (stmt::T_SELECT == id_name_pair.stmt_type_) {
|
|
start_id = &start_ids[0];
|
|
} else if (stmt::T_INSERT == id_name_pair.stmt_type_) {
|
|
start_id = &start_ids[1];
|
|
} else if (stmt::T_REPLACE == id_name_pair.stmt_type_) {
|
|
start_id = &start_ids[2];
|
|
} else if (stmt::T_DELETE == id_name_pair.stmt_type_) {
|
|
start_id = &start_ids[3];
|
|
} else if (stmt::T_UPDATE == id_name_pair.stmt_type_) {
|
|
start_id = &start_ids[4];
|
|
}
|
|
if (OB_FAIL(get_dml_stmt_name(id_name_pair.stmt_type_, buf, OB_MAX_QB_NAME_LENGTH, pos))) {
|
|
LOG_WARN("Get dml stmt name", K(ret));
|
|
} else if (OB_FAIL(append_id_to_stmt_name(buf, OB_MAX_QB_NAME_LENGTH, pos, *start_id))) {
|
|
LOG_WARN("Failed to append id to stmt name", K(ret));
|
|
} else {
|
|
ObString generate_name(pos, buf);
|
|
if (OB_FAIL(ob_write_string(*allocator, generate_name, id_name_pair.origin_name_))) {
|
|
LOG_WARN("Write string error", K(ret));
|
|
} else if (!id_name_pair.name_.empty()) {
|
|
// do nothing
|
|
} else if (OB_FAIL(ob_write_string(*allocator, generate_name, id_name_pair.name_))) {
|
|
LOG_WARN("Write string error", K(ret));
|
|
} else {
|
|
} // do nothing.
|
|
}
|
|
} else {
|
|
} // other stmt type need not generate stmt name
|
|
}
|
|
} else {
|
|
} // do nothing
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::get_dml_stmt_name(stmt::StmtType stmt_type, char* buf, int64_t buf_len, int64_t& pos)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_ISNULL(buf)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Input buf should not be NULL", K(ret));
|
|
} else if (pos < buf_len) {
|
|
switch (stmt_type) {
|
|
case stmt::T_SELECT: {
|
|
if (OB_FAIL(BUF_PRINTF("SEL$"))) {
|
|
LOG_WARN("Append name to buf error", K(ret));
|
|
}
|
|
break;
|
|
}
|
|
case stmt::T_INSERT: {
|
|
if (OB_FAIL(BUF_PRINTF("INS$"))) {
|
|
LOG_WARN("Append name to buf error", K(ret));
|
|
}
|
|
break;
|
|
}
|
|
case stmt::T_REPLACE: {
|
|
if (OB_FAIL(BUF_PRINTF("REP$"))) {
|
|
LOG_WARN("Append name to buf error", K(ret));
|
|
}
|
|
break;
|
|
}
|
|
case stmt::T_UPDATE: {
|
|
if (OB_FAIL(BUF_PRINTF("UPD$"))) {
|
|
LOG_WARN("Append name to buf error", K(ret));
|
|
}
|
|
break;
|
|
}
|
|
case stmt::T_DELETE: {
|
|
if (OB_FAIL(BUF_PRINTF("DEL$"))) {
|
|
LOG_WARN("Append name to buf error", K(ret));
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Invalid stmt type to get dml name", K(ret));
|
|
}
|
|
}
|
|
} else {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("Buffer size not enough", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::append_id_to_stmt_name(char* buf, int64_t buf_len, int64_t& pos, int64_t& id_start)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(buf)) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Buf should not be NULL", K(ret));
|
|
} else if (pos >= buf_len) {
|
|
ret = OB_SIZE_OVERFLOW;
|
|
LOG_WARN("Buf size not enough", K(ret));
|
|
} else {
|
|
bool find_unique = false;
|
|
int64_t id = id_start;
|
|
int64_t old_pos = pos;
|
|
while (!find_unique && OB_SUCC(ret)) {
|
|
pos = old_pos;
|
|
if (OB_FAIL(BUF_PRINTF("%ld", id))) {
|
|
LOG_WARN("Append idx to stmt_name error", K(ret));
|
|
} else {
|
|
bool find_dup = false;
|
|
for (int64_t i = 0; !find_dup && i < stmt_id_name_map_.count(); ++i) {
|
|
if (0 == stmt_id_name_map_.at(i).origin_name_.case_compare(buf)) {
|
|
find_dup = true;
|
|
} else {
|
|
} // do nothing
|
|
} // end of for
|
|
find_unique = !find_dup;
|
|
++id;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && find_unique) {
|
|
id_start = id;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::find_stmt_id(const ObString& stmt_name, int64_t& stmt_id)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
stmt_id = -1;
|
|
if (stmt_name.empty()) {
|
|
ret = OB_INVALID_ARGUMENT;
|
|
LOG_WARN("Failed to find stmt id", K(ret));
|
|
} else {
|
|
bool find_stmt = false;
|
|
for (int64_t idx = 0; OB_SUCC(ret) && !find_stmt && idx < stmt_id_name_map_.count(); ++idx) {
|
|
if (0 == stmt_name.case_compare(stmt_id_name_map_.at(idx).name_)) {
|
|
stmt_id = stmt_id_name_map_.at(idx).id_;
|
|
find_stmt = true;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
ObStmt* ObQueryCtx::find_stmt_by_id(const int64_t stmt_id)
|
|
{
|
|
ObStmt* stmt = NULL;
|
|
if (stmt_id == OB_INVALID_STMT_ID) {
|
|
} else {
|
|
for (int64_t idx = 0; idx < id_stmt_map_.count(); ++idx) {
|
|
if (stmt_id == id_stmt_map_.at(idx).first) {
|
|
stmt = id_stmt_map_.at(idx).second;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return stmt;
|
|
}
|
|
|
|
int ObQueryCtx::replace_name_in_tables(const ObSQLSessionInfo& session_info, ObDMLStmt& stmt,
|
|
ObIArray<ObTablesInHint>& arr, uint64_t table_id, ObString& to_db_name, ObString& to_table_name)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < arr.count(); i++) {
|
|
if (OB_FAIL(ObStmtHint::replace_name_in_hint(
|
|
session_info, stmt, arr.at(i).tables_, table_id, to_db_name, to_table_name))) {
|
|
LOG_WARN("Failed to replace name", K(ret));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::replace_name_for_single_table_view(const ObSQLSessionInfo& session_info, ObDMLStmt* stmt,
|
|
uint64_t table_id, ObString& to_db_name, ObString& to_table_name)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(stmt)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("NULL stmt", K(ret));
|
|
} else if (OB_FAIL(replace_name_in_tables(session_info, *stmt, join_order_, table_id, to_db_name, to_table_name))) {
|
|
LOG_WARN("failed to replace in join_order_", K(ret));
|
|
} else if (OB_FAIL(replace_name_in_tables(session_info, *stmt, use_merge_, table_id, to_db_name, to_table_name))) {
|
|
LOG_WARN("failed to replace in use_merge_", K(ret));
|
|
} else if (OB_FAIL(replace_name_in_tables(session_info, *stmt, no_use_merge_, table_id, to_db_name, to_table_name))) {
|
|
LOG_WARN("failed to replace in no use_merge_", K(ret));
|
|
} else if (OB_FAIL(replace_name_in_tables(session_info, *stmt, use_hash_, table_id, to_db_name, to_table_name))) {
|
|
LOG_WARN("failed to replace in use_hash_", K(ret));
|
|
} else if (OB_FAIL(replace_name_in_tables(session_info, *stmt, no_use_hash_, table_id, to_db_name, to_table_name))) {
|
|
LOG_WARN("failed to replace in no_use_hash_", K(ret));
|
|
} else if (OB_FAIL(replace_name_in_tables(session_info, *stmt, use_nl_, table_id, to_db_name, to_table_name))) {
|
|
LOG_WARN("failed to replace in use_nl_", K(ret));
|
|
} else if (OB_FAIL(replace_name_in_tables(session_info, *stmt, no_use_nl_, table_id, to_db_name, to_table_name))) {
|
|
LOG_WARN("failed to replace in no use_nl_", K(ret));
|
|
} else if (OB_FAIL(replace_name_in_tables(session_info, *stmt, use_bnl_, table_id, to_db_name, to_table_name))) {
|
|
LOG_WARN("failed to replace in use_bnl_", K(ret));
|
|
} else if (OB_FAIL(replace_name_in_tables(session_info, *stmt, no_use_bnl_, table_id, to_db_name, to_table_name))) {
|
|
LOG_WARN("failed to replace in no use_bnl_", K(ret));
|
|
} else if (OB_FAIL(
|
|
replace_name_in_tables(session_info, *stmt, px_join_filter_, table_id, to_db_name, to_table_name))) {
|
|
LOG_WARN("failed to replace in px join filter", K(ret));
|
|
} else if (OB_FAIL(replace_name_in_tables(
|
|
session_info, *stmt, no_px_join_filter_, table_id, to_db_name, to_table_name))) {
|
|
LOG_WARN("failed to replace in no px join filter", K(ret));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::distribute_hint_to_stmt()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (OB_FAIL(distribute_index_hint())) {
|
|
LOG_WARN("Failed to distribute index hint", K(ret));
|
|
} else if (OB_FAIL(distribute_pq_hint())) {
|
|
LOG_WARN("Failed to distribute pq hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(join_order_, ObStmtHint::LEADING))) {
|
|
LOG_WARN("Failed to distribute leading hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(use_merge_, ObStmtHint::USE_MERGE))) {
|
|
LOG_WARN("Failed to distribute use merge hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(no_use_merge_, ObStmtHint::NO_USE_MERGE))) {
|
|
LOG_WARN("Failed to distribute no use merge hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(use_hash_, ObStmtHint::USE_HASH))) {
|
|
LOG_WARN("Failed to distribute use hash hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(no_use_hash_, ObStmtHint::NO_USE_HASH))) {
|
|
LOG_WARN("Failed to distribute no use hash hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(use_nl_, ObStmtHint::USE_NL))) {
|
|
LOG_WARN("Failed to distribute use nl hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(no_use_nl_, ObStmtHint::NO_USE_NL))) {
|
|
LOG_WARN("Failed to distribute no use nl hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(use_bnl_, ObStmtHint::USE_BNL))) {
|
|
LOG_WARN("Failed to distribute use bnl hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(no_use_bnl_, ObStmtHint::NO_USE_BNL))) {
|
|
LOG_WARN("Failed to distribute no use bnl hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(use_nl_materialization_, ObStmtHint::USE_NL_MATERIALIZATION))) {
|
|
LOG_WARN("Failed to distribute use material nl hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(no_use_nl_materialization_, ObStmtHint::NO_USE_NL_MATERIALIZATION))) {
|
|
LOG_WARN("Failed to distribute no use material nl hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(px_join_filter_, ObStmtHint::PX_JOIN_FILTER))) {
|
|
LOG_WARN("Failed to distribute leading hint", K(ret));
|
|
} else if (OB_FAIL(distribute_tables_hint(no_px_join_filter_, ObStmtHint::NO_PX_JOIN_FILTER))) {
|
|
LOG_WARN("Failed to distribute leading hint", K(ret));
|
|
} else if (OB_FAIL(distribute_rewrite_hint(no_expand_, ObStmtHint::NO_EXPAND))) {
|
|
LOG_WARN("Failed to distribute no expand hint", K(ret));
|
|
} else if (OB_FAIL(distribute_rewrite_hint(use_concat_, ObStmtHint::USE_CONCAT))) {
|
|
LOG_WARN("Failed to distribute use concat hint", K(ret));
|
|
} else if (OB_FAIL(distribute_rewrite_hint(merge_, ObStmtHint::MERGE))) {
|
|
LOG_WARN("Failed to distribute merge hint", K(ret));
|
|
} else if (OB_FAIL(distribute_rewrite_hint(no_merge_, ObStmtHint::NO_MERGE))) {
|
|
LOG_WARN("Failed to distribute no merge hint", K(ret));
|
|
} else if (OB_FAIL(distribute_rewrite_hint(unnest_, ObStmtHint::UNNEST))) {
|
|
LOG_WARN("Failed to distribute unnest hint", K(ret));
|
|
} else if (OB_FAIL(distribute_rewrite_hint(no_unnest_, ObStmtHint::NO_UNNEST))) {
|
|
LOG_WARN("Failed to distribute no unnest hint", K(ret));
|
|
} else if (OB_FAIL(distribute_rewrite_hint(place_group_by_, ObStmtHint::PLACE_GROUPBY))) {
|
|
LOG_WARN("Failed to distribute place group by hint", K(ret));
|
|
} else if (OB_FAIL(distribute_rewrite_hint(no_place_group_by_, ObStmtHint::NO_PLACE_GROUPBY))) {
|
|
LOG_WARN("Failed to distribute no place group by hint", K(ret));
|
|
} else if (OB_FAIL(distribute_rewrite_hint(no_pred_deduce_, ObStmtHint::NO_PRED_DEDUCE))) {
|
|
LOG_WARN("Failed to distribute no pred deduce hint", K(ret));
|
|
} else {
|
|
} // do nothing.
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::distribute_index_hint()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
if (org_indexes_.count() > 0) {
|
|
ObStmt* stmt = NULL;
|
|
int64_t stmt_id = OB_INVALID_STMT_ID;
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < org_indexes_.count(); ++idx) {
|
|
ObQNameIndexHint& q_index_hint = org_indexes_.at(idx);
|
|
if (q_index_hint.distributed_) {
|
|
// been distributed.
|
|
} else if (OB_FAIL(find_stmt_id(q_index_hint.qb_name_, stmt_id))) {
|
|
LOG_WARN("Failed to find stmt id", K(ret));
|
|
} else if (OB_INVALID_STMT_ID != stmt_id) {
|
|
if (OB_UNLIKELY(NULL == (stmt = find_stmt_by_id(stmt_id)))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Failed to find stmt", K(ret));
|
|
} else if (stmt->is_dml_stmt()) {
|
|
if (OB_FAIL(
|
|
static_cast<ObDMLStmt*>(stmt)->get_stmt_hint().org_indexes_.push_back(q_index_hint.index_hint_))) {
|
|
LOG_WARN("Failed to add index hint to stmt", K(ret));
|
|
} else {
|
|
q_index_hint.distributed_ = true;
|
|
}
|
|
} else {
|
|
} // do nothing
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::distribute_pq_hint()
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
|
|
// pq distribute hint
|
|
FOREACH_X(hint, org_pq_distributes_, OB_SUCC(ret))
|
|
{
|
|
ObStmt* stmt = NULL;
|
|
int64_t stmt_id = OB_INVALID_STMT_ID;
|
|
if (hint->distributed_) {
|
|
// already distributed
|
|
} else if (OB_FAIL(find_stmt_id(hint->qb_name_, stmt_id))) {
|
|
LOG_WARN("failed to find stmt id", K(ret), "qb_name", hint->qb_name_);
|
|
} else if (OB_INVALID_STMT_ID != stmt_id) {
|
|
if (OB_ISNULL(stmt = find_stmt_by_id(stmt_id))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("find NULL stmt", K(ret), K(stmt_id));
|
|
} else if (stmt->is_dml_stmt()) {
|
|
if (OB_FAIL(static_cast<ObDMLStmt*>(stmt)->get_stmt_hint().org_pq_distributes_.push_back(*hint))) {
|
|
LOG_WARN("array push back failed", K(ret));
|
|
} else {
|
|
hint->distributed_ = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// pq map hint
|
|
FOREACH_X(hint, org_pq_maps_, OB_SUCC(ret))
|
|
{
|
|
ObStmt* stmt = NULL;
|
|
int64_t stmt_id = OB_INVALID_STMT_ID;
|
|
if (hint->distributed_) {
|
|
// already distributed
|
|
} else if (OB_FAIL(find_stmt_id(hint->qb_name_, stmt_id))) {
|
|
LOG_WARN("failed to find stmt id", K(ret), "qb_name", hint->qb_name_);
|
|
} else if (OB_INVALID_STMT_ID != stmt_id) {
|
|
if (OB_ISNULL(stmt = find_stmt_by_id(stmt_id))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("find NULL stmt", K(ret), K(stmt_id));
|
|
} else if (stmt->is_dml_stmt()) {
|
|
if (OB_FAIL(static_cast<ObDMLStmt*>(stmt)->get_stmt_hint().org_pq_maps_.push_back(*hint))) {
|
|
LOG_WARN("array push back failed", K(ret));
|
|
} else {
|
|
hint->distributed_ = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::distribute_rewrite_hint(const common::ObIArray<ObString>& qb_names, ObStmtHint::RewriteHint hint)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObStmt* stmt = NULL;
|
|
int64_t stmt_id = OB_INVALID_STMT_ID;
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < qb_names.count(); ++idx) {
|
|
if (OB_FAIL(find_stmt_id(qb_names.at(idx), stmt_id))) {
|
|
LOG_WARN("Failed to find stmt id", K(ret));
|
|
} else if (OB_INVALID_STMT_ID != stmt_id) {
|
|
if (OB_ISNULL(stmt = find_stmt_by_id(stmt_id))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Failed to find stmt", K(ret));
|
|
} else if (stmt->is_dml_stmt()) {
|
|
ObStmtHint& stmt_hint = static_cast<ObDMLStmt*>(stmt)->get_stmt_hint();
|
|
if (ObStmtHint::NO_EXPAND == hint) {
|
|
stmt_hint.use_expand_ = ObUseRewriteHint::NO_EXPAND;
|
|
} else if (ObStmtHint::USE_CONCAT == hint) {
|
|
stmt_hint.use_expand_ = ObUseRewriteHint::USE_CONCAT;
|
|
} else if (ObStmtHint::MERGE == hint) {
|
|
stmt_hint.use_view_merge_ = ObUseRewriteHint::V_MERGE;
|
|
} else if (ObStmtHint::NO_MERGE == hint) {
|
|
stmt_hint.use_view_merge_ = ObUseRewriteHint::NO_V_MERGE;
|
|
} else if (ObStmtHint::UNNEST == hint) {
|
|
stmt_hint.use_unnest_ = ObUseRewriteHint::UNNEST;
|
|
} else if (ObStmtHint::NO_UNNEST == hint) {
|
|
stmt_hint.use_unnest_ = ObUseRewriteHint::NO_UNNEST;
|
|
} else if (ObStmtHint::PLACE_GROUPBY == hint) {
|
|
stmt_hint.use_place_groupby_ = ObUseRewriteHint::PLACE_GROUPBY;
|
|
} else if (ObStmtHint::NO_PLACE_GROUPBY == hint) {
|
|
stmt_hint.use_place_groupby_ = ObUseRewriteHint::NO_PLACE_GROUPBY;
|
|
} else if (ObStmtHint::NO_PRED_DEDUCE == hint) {
|
|
stmt_hint.use_pred_deduce_ = ObUseRewriteHint::NO_PRED_DEDUCE;
|
|
} else {
|
|
} // do nothing.
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::distribute_tables_hint(ObIArray<ObTablesInHint>& tables_hint_arr, ObStmtHint::TablesHint hint)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (tables_hint_arr.count() > 0) {
|
|
ObStmt* stmt = NULL;
|
|
int64_t stmt_id = OB_INVALID_STMT_ID;
|
|
for (int64_t idx = 0; OB_SUCC(ret) && idx < tables_hint_arr.count(); ++idx) {
|
|
ObTablesInHint& tables_hint = tables_hint_arr.at(idx);
|
|
if (tables_hint.distributed_) {
|
|
// been distributed.
|
|
} else if (OB_FAIL(find_stmt_id(tables_hint.qb_name_, stmt_id))) {
|
|
LOG_WARN("Failed to find stmt id", K(ret));
|
|
} else if (OB_INVALID_STMT_ID != stmt_id) {
|
|
if (OB_UNLIKELY(NULL == (stmt = find_stmt_by_id(stmt_id)))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Failed to find stmt", K(ret));
|
|
} else if (stmt->is_dml_stmt()) {
|
|
ObStmtHint& stmt_hint = static_cast<ObDMLStmt*>(stmt)->get_stmt_hint();
|
|
ObIArray<ObTableInHint>* p_table_hint_arr = stmt_hint.get_join_tables(hint);
|
|
ObIArray<std::pair<uint8_t, uint8_t>>* p_join_order_pair_arr = &stmt_hint.join_order_pairs_;
|
|
if (OB_ISNULL(p_table_hint_arr)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("Hint not known", K(ret), K(hint));
|
|
} else if (ObStmtHint::LEADING == hint && p_table_hint_arr->count() > 0 &&
|
|
(OB_FALSE_IT(p_table_hint_arr->reset()) || OB_FALSE_IT(p_join_order_pair_arr->reset()))) {
|
|
/* prior leading hint ignored if query ctx has leading hint */
|
|
} else if (OB_FAIL(append(*p_table_hint_arr, tables_hint.tables_))) {
|
|
LOG_WARN("Failed to add index hint to stmt", K(ret));
|
|
} else if (ObStmtHint::LEADING == hint &&
|
|
OB_FAIL(append(*p_join_order_pair_arr, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else if (ObStmtHint::USE_HASH == hint &&
|
|
OB_FAIL(append(stmt_hint.use_hash_order_pairs_, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else if (ObStmtHint::USE_MERGE == hint &&
|
|
OB_FAIL(append(stmt_hint.use_merge_order_pairs_, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else if (ObStmtHint::USE_NL == hint &&
|
|
OB_FAIL(append(stmt_hint.use_nl_order_pairs_, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else if (ObStmtHint::USE_BNL == hint &&
|
|
OB_FAIL(append(stmt_hint.use_bnl_order_pairs_, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else if (ObStmtHint::NO_USE_HASH == hint &&
|
|
OB_FAIL(append(stmt_hint.no_use_hash_order_pairs_, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else if (ObStmtHint::NO_USE_MERGE == hint &&
|
|
OB_FAIL(append(stmt_hint.no_use_merge_order_pairs_, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else if (ObStmtHint::NO_USE_NL == hint &&
|
|
OB_FAIL(append(stmt_hint.no_use_nl_order_pairs_, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else if (ObStmtHint::NO_USE_BNL == hint &&
|
|
OB_FAIL(append(stmt_hint.no_use_bnl_order_pairs_, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else if (ObStmtHint::USE_NL_MATERIALIZATION == hint &&
|
|
OB_FAIL(append(stmt_hint.use_nl_materialization_order_pairs_, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else if (ObStmtHint::NO_USE_NL_MATERIALIZATION == hint &&
|
|
OB_FAIL(append(stmt_hint.no_use_nl_materialization_order_pairs_, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else if (ObStmtHint::PX_JOIN_FILTER == hint &&
|
|
OB_FAIL(append(stmt_hint.px_join_filter_order_pairs_, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else if (ObStmtHint::NO_PX_JOIN_FILTER == hint &&
|
|
OB_FAIL(append(stmt_hint.no_px_join_filter_order_pairs_, tables_hint.join_order_pairs_))) {
|
|
LOG_WARN("Failed to add join order hint to stmt", K(ret));
|
|
} else {
|
|
tables_hint.distributed_ = true;
|
|
}
|
|
} else {
|
|
// do nothing
|
|
}
|
|
} else {
|
|
// do nothing
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::get_stmt_name_by_id(const int64_t stmt_id, common::ObString& stmt_name) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool is_found = false;
|
|
for (int64_t i = 0; OB_SUCC(ret) && !is_found && i < stmt_id_name_map_.count(); ++i) {
|
|
if (stmt_id == stmt_id_name_map_.at(i).id_) {
|
|
stmt_name = stmt_id_name_map_.at(i).name_;
|
|
is_found = true;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && !is_found) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::get_stmt_org_name_by_id(const int64_t stmt_id, common::ObString& org_name) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool is_found = false;
|
|
for (int64_t i = 0; OB_SUCC(ret) && !is_found && i < stmt_id_name_map_.count(); ++i) {
|
|
if (stmt_id == stmt_id_name_map_.at(i).id_) {
|
|
org_name = stmt_id_name_map_.at(i).origin_name_;
|
|
is_found = true;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && !is_found) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::get_stmt_org_name(const common::ObString& stmt_name, common::ObString& org_name) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool is_found = false;
|
|
for (int64_t i = 0; OB_SUCC(ret) && !is_found && i < stmt_id_name_map_.count(); ++i) {
|
|
if (0 == stmt_name.case_compare(stmt_id_name_map_.at(i).name_)) {
|
|
org_name = stmt_id_name_map_.at(i).origin_name_;
|
|
is_found = true;
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && !is_found) {
|
|
ret = OB_ENTRY_NOT_EXIST;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::print_qb_name_hint(planText& plan_text) const
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
char* buf = plan_text.buf;
|
|
int64_t& buf_len = plan_text.buf_len;
|
|
int64_t& pos = plan_text.pos;
|
|
bool is_oneline = plan_text.is_oneline_;
|
|
OutlineType outline_type = plan_text.outline_type_;
|
|
ObString qb_name;
|
|
if (USED_HINT == outline_type) {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < valid_qb_name_stmt_ids_.count(); ++i) {
|
|
uint64_t cur_stmt_id = valid_qb_name_stmt_ids_.at(i);
|
|
qb_name.reset();
|
|
if (OB_FAIL(get_stmt_name_by_id(cur_stmt_id, qb_name))) {
|
|
LOG_WARN("fail to get stmt name", K(ret), K(cur_stmt_id));
|
|
} else if (!is_oneline && OB_FAIL(BUF_PRINTF("\n"))) {
|
|
} else if (OB_FAIL(BUF_PRINTF(ObStmtHint::get_outline_indent(is_oneline)))) {
|
|
} else if (OB_FAIL(BUF_PRINTF(ObStmtHint::QB_NAME_HINT))) {
|
|
} else if (OB_FAIL(BUF_PRINTF("(%.*s)", qb_name.length(), qb_name.ptr()))) {
|
|
} else { /*do nothing*/
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool ObQueryCtx::is_cross_tenant_query(uint64_t effective_tenant_id) const
|
|
{
|
|
bool bret = false;
|
|
for (int64_t i = 0; !bret && i < table_partition_infos_.count(); ++i) {
|
|
if (table_partition_infos_.at(i) != NULL) {
|
|
uint64_t cur_tenant_id = extract_tenant_id(table_partition_infos_.at(i)->get_ref_table_id());
|
|
bret = (cur_tenant_id != effective_tenant_id);
|
|
}
|
|
}
|
|
return bret;
|
|
}
|
|
|
|
int ObSqlCtx::set_partition_infos(const ObTablePartitionInfoArray& info, ObIAllocator& allocator)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
int64_t count = info.count();
|
|
partition_infos_.reset();
|
|
if (count > 0) {
|
|
partition_infos_.set_allocator(&allocator);
|
|
if (OB_FAIL(partition_infos_.init(count))) {
|
|
LOG_WARN("init partition info failed", K(ret), K(count));
|
|
} else {
|
|
for (int64_t i = 0; i < count && OB_SUCC(ret); ++i) {
|
|
if (OB_FAIL(partition_infos_.push_back(info.at(i)))) {
|
|
LOG_WARN("push partition info failed", K(ret), K(count));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlCtx::set_acs_index_info(const ObIArray<ObAcsIndexInfo*>& acs_index_infos, ObIAllocator& allocator)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (acs_index_infos.count() > 0) {
|
|
acs_index_infos_.reset();
|
|
acs_index_infos_.set_allocator(&allocator);
|
|
if (OB_FAIL(acs_index_infos_.init(acs_index_infos.count()))) {
|
|
LOG_WARN("init acs index infos failed", K(ret));
|
|
} else {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < acs_index_infos.count(); i++) {
|
|
if (OB_ISNULL(acs_index_infos.at(i))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected null", K(ret));
|
|
} else if (OB_FAIL(acs_index_infos_.push_back(acs_index_infos.at(i)))) {
|
|
LOG_WARN("failed to push back acs index info", K(ret));
|
|
} else { /*do nothing*/
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlCtx::set_related_user_var_names(const ObIArray<ObString>& user_var_names, ObIAllocator& allocator)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (user_var_names.count() > 0) {
|
|
related_user_var_names_.reset();
|
|
related_user_var_names_.set_allocator(&allocator);
|
|
if (OB_FAIL(related_user_var_names_.init(user_var_names.count()))) {
|
|
LOG_WARN("failed to init related_user_var_names", K(ret));
|
|
} else {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < user_var_names.count(); i++) {
|
|
if (OB_FAIL(related_user_var_names_.push_back(user_var_names.at(i)))) {
|
|
LOG_WARN("failed to push back user var names", K(ret));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (OB_FAIL(ret)) {
|
|
related_user_var_names_.reset();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlCtx::set_location_constraints(const ObLocationConstraintContext& location_constraint, ObIAllocator& allocator)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
base_constraints_.reset();
|
|
strict_constraints_.reset();
|
|
non_strict_constraints_.reset();
|
|
const ObIArray<LocationConstraint>& base_constraints = location_constraint.base_table_constraints_;
|
|
const ObIArray<ObPwjConstraint*>& strict_constraints = location_constraint.strict_constraints_;
|
|
const ObIArray<ObPwjConstraint*>& non_strict_constraints = location_constraint.non_strict_constraints_;
|
|
if (base_constraints.count() > 0) {
|
|
base_constraints_.set_allocator(&allocator);
|
|
if (OB_FAIL(base_constraints_.init(base_constraints.count()))) {
|
|
LOG_WARN("init base constraints failed", K(ret));
|
|
} else {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < base_constraints.count(); i++) {
|
|
if (OB_FAIL(base_constraints_.push_back(base_constraints.at(i)))) {
|
|
LOG_WARN("failed to push back base constraint", K(ret));
|
|
} else {
|
|
// sharding_info_ is only used in the plan generation phase
|
|
base_constraints_.at(i).sharding_info_ = NULL;
|
|
}
|
|
}
|
|
LOG_DEBUG("set base constraints", K(base_constraints.count()));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && strict_constraints.count() > 0) {
|
|
strict_constraints_.set_allocator(&allocator);
|
|
if (OB_FAIL(strict_constraints_.init(strict_constraints.count()))) {
|
|
LOG_WARN("init strict constraints failed", K(ret));
|
|
} else {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < strict_constraints.count(); i++) {
|
|
if (OB_FAIL(strict_constraints_.push_back(strict_constraints.at(i)))) {
|
|
LOG_WARN("failed to push back location constraint", K(ret));
|
|
}
|
|
}
|
|
LOG_DEBUG("set strict constraints", K(strict_constraints.count()));
|
|
}
|
|
}
|
|
if (OB_SUCC(ret) && non_strict_constraints.count() > 0) {
|
|
non_strict_constraints_.set_allocator(&allocator);
|
|
if (OB_FAIL(non_strict_constraints_.init(non_strict_constraints.count()))) {
|
|
LOG_WARN("init non strict constraints failed", K(ret));
|
|
} else {
|
|
for (int64_t i = 0; OB_SUCC(ret) && i < non_strict_constraints.count(); i++) {
|
|
if (OB_FAIL(non_strict_constraints_.push_back(non_strict_constraints.at(i)))) {
|
|
LOG_WARN("failed to push back location constraint", K(ret));
|
|
}
|
|
}
|
|
LOG_DEBUG("set non strict constraints", K(non_strict_constraints.count()));
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObSqlCtx::set_multi_stmt_rowkey_pos(
|
|
const common::ObIArray<int64_t>& multi_stmt_rowkey_pos, common::ObIAllocator& alloctor)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (!multi_stmt_rowkey_pos.empty()) {
|
|
multi_stmt_rowkey_pos_.set_allocator(&alloctor);
|
|
if (OB_FAIL(multi_stmt_rowkey_pos_.init(multi_stmt_rowkey_pos.count()))) {
|
|
LOG_WARN("failed to init rowkey count", K(ret));
|
|
} else if (OB_FAIL(append(multi_stmt_rowkey_pos_, multi_stmt_rowkey_pos))) {
|
|
LOG_WARN("failed to append multi stmt rowkey pos", K(ret));
|
|
} else { /*do nothing*/
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::add_tracing_hint(ObIArray<uint64_t>& tracing_ids)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool find = false;
|
|
ARRAY_FOREACH(tracing_ids, idx)
|
|
{
|
|
find = false;
|
|
ARRAY_FOREACH(monitoring_ids_, n)
|
|
{
|
|
if (tracing_ids.at(idx) == monitoring_ids_.at(n).id_) {
|
|
monitoring_ids_.at(n).flags_ = monitoring_ids_.at(n).flags_ & OB_MONITOR_TRACING;
|
|
find = true;
|
|
}
|
|
}
|
|
if (!find) {
|
|
ObMonitorHint hint;
|
|
hint.id_ = tracing_ids.at(idx);
|
|
hint.flags_ = hint.flags_ | OB_MONITOR_TRACING;
|
|
if (OB_FAIL(monitoring_ids_.push_back(hint))) {
|
|
LOG_WARN("Failed to push back tracing", K(ret));
|
|
}
|
|
}
|
|
}
|
|
LOG_DEBUG("add tracing hint", K(monitoring_ids_));
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::add_stat_hint(ObIArray<uint64_t>& stat_ids)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool find = false;
|
|
ARRAY_FOREACH(stat_ids, idx)
|
|
{
|
|
find = false;
|
|
ARRAY_FOREACH(monitoring_ids_, n)
|
|
{
|
|
if (stat_ids.at(idx) == monitoring_ids_.at(n).id_) {
|
|
monitoring_ids_.at(n).flags_ = monitoring_ids_.at(n).flags_ | OB_MONITOR_STAT;
|
|
find = true;
|
|
}
|
|
}
|
|
if (!find) {
|
|
ObMonitorHint hint;
|
|
hint.id_ = stat_ids.at(idx);
|
|
hint.flags_ = hint.flags_ | OB_MONITOR_STAT;
|
|
if (OB_FAIL(monitoring_ids_.push_back(hint))) {
|
|
LOG_WARN("Failed to push back stat", K(ret));
|
|
}
|
|
}
|
|
}
|
|
LOG_DEBUG("add stat hint", K(monitoring_ids_));
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::add_pq_map_hint(common::ObString& qb_name, ObOrgPQMapHint& pq_map_hint)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
ObQBNamePQMapHint hint(qb_name, pq_map_hint);
|
|
if (OB_FAIL(org_pq_maps_.push_back(hint))) {
|
|
LOG_WARN("fail to push back pq map", K(ret), K(hint));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::add_temp_table(ObSqlTempTableInfo* temp_table_info)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
if (OB_ISNULL(temp_table_info)) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected null", K(temp_table_info), K(ret));
|
|
} else if (OB_FAIL(temp_table_infos_.push_back(temp_table_info))) {
|
|
LOG_WARN("failed to push back temp table info", K(ret));
|
|
} else { /*do nothing*/
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ObQueryCtx::get_temp_table_plan(const uint64_t temp_table_id, ObLogicalOperator*& temp_table_insert)
|
|
{
|
|
int ret = OB_SUCCESS;
|
|
bool is_found = false;
|
|
for (int64_t i = 0; OB_SUCC(ret) && !is_found && i < temp_table_infos_.count(); i++) {
|
|
if (OB_ISNULL(temp_table_infos_.at(i))) {
|
|
ret = OB_ERR_UNEXPECTED;
|
|
LOG_WARN("get unexpected null", K(ret));
|
|
} else if (temp_table_infos_.at(i)->ref_table_id_ == temp_table_id) {
|
|
temp_table_insert = temp_table_infos_.at(i)->table_plan_;
|
|
is_found = true;
|
|
} else { /*do nothing.*/
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
} // namespace sql
|
|
} // namespace oceanbase
|