Files
oceanbase/src/share/stat/ob_col_stat_sql_service.cpp
oceanbase-admin cea7de1475 init push
2021-05-31 22:56:52 +08:00

976 lines
44 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 COMMON
#include "share/stat/ob_col_stat_sql_service.h"
#include "lib/oblog/ob_log.h"
#include "lib/oblog/ob_log_module.h"
#include "lib/string/ob_sql_string.h"
#include "lib/mysqlclient/ob_mysql_proxy.h"
#include "lib/mysqlclient/ob_mysql_transaction.h"
#include "lib/mysqlclient/ob_mysql_result.h"
#include "lib/mysqlclient/ob_mysql_connection.h"
#include "lib/mysqlclient/ob_mysql_statement.h"
#include "lib/mysqlclient/ob_mysql_connection_pool.h"
#include "lib/utility/ob_print_utils.h"
#include "lib/compress/ob_compressor_pool.h"
#include "common/ob_partition_key.h"
#include "common/ob_timeout_ctx.h"
#include "share/ob_dml_sql_splicer.h"
#include "share/config/ob_server_config.h"
#include "share/partition_table/ob_ipartition_table.h"
#include "share/schema/ob_schema_utils.h"
#include "share/schema/ob_multi_version_schema_service.h"
#include "share/stat/ob_table_stat.h"
#include "observer/ob_server_struct.h"
#include "observer/ob_sql_client_decorator.h"
#define MY_ALL_COL_STAT_COLUMN_NAME \
"tenant_id, " \
"table_id, " \
"partition_id, " \
"column_id, " \
"version, " \
"last_rebuild_version," \
"num_distinct, " \
"num_null," \
"min_value, " \
"max_value, " \
"llc_bitmap," \
"llc_bitmap_size "
#define USER_TAB_COL_STATISTICS "__all_column_statistic"
#define MY_FETCH_COL_STAT_SQL "SELECT " MY_ALL_COL_STAT_COLUMN_NAME " FROM " USER_TAB_COL_STATISTICS
#define REPLACE_COL_STAT_SQL "REPLACE INTO " USER_TAB_COL_STATISTICS "(" MY_ALL_COL_STAT_COLUMN_NAME ") "
#define MY_ALL_TABLE_STAT_COLUMN_NAME \
"tenant_id, " \
"table_id", \
"partition_id, " \
"partition_cnt, " \
"row_count, " \
"data_size," \
"data_version "
#define DEFINE_SQL_CLIENT_RETRY_WEAK_FOR_STAT(sql_client) \
const bool did_use_weak = false; \
const bool did_use_retry = false; \
const int64_t snapshot_timestamp = OB_INVALID_TIMESTAMP; \
const bool check_sys_variable = false; \
ObSQLClientRetryWeak sql_client_retry_weak( \
sql_client, did_use_weak, did_use_retry, snapshot_timestamp, check_sys_variable);
namespace oceanbase {
using namespace share;
using namespace share::schema;
namespace share {
class ObIPartitiontable;
}
namespace common {
const char* ObTableColStatSqlService::bitmap_compress_lib_name = "zlib_1.0";
ObTableColStatSqlService::ObTableColStatSqlService() : inited_(false), mysql_proxy_(NULL), config_(NULL)
{}
ObTableColStatSqlService::~ObTableColStatSqlService()
{}
int ObTableColStatSqlService::init(ObMySQLProxy* proxy, ObServerConfig* config)
{
int ret = OB_SUCCESS;
lib::ObMutexGuard guard(mutex_);
if (NULL == proxy) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "client proxy is null", K(ret));
} else if (inited_) {
ret = OB_INIT_TWICE;
COMMON_LOG(WARN, "sql service have already been initialized.", K(ret));
} else {
mysql_proxy_ = proxy;
config_ = config;
inited_ = true;
}
return ret;
}
// init virtual table converter
int ObTableColStatSqlService::init_vt_converter(
uint64_t tenant_id, uint64_t ref_table_id, uint64_t column_id, ObStatConverterInfo& stat_converter_info)
{
int ret = OB_SUCCESS;
ObSEArray<uint64_t, 1> column_ids;
if (OB_FAIL(column_ids.push_back(column_id))) {
LOG_WARN("failed to push back column ids", K(ret));
} else if (OB_FAIL(init_vt_converter(tenant_id, ref_table_id, column_ids, stat_converter_info))) {
LOG_WARN("failed to init vt convert", K(ret));
}
return ret;
}
int ObTableColStatSqlService::init_vt_converter(
uint64_t tenant_id, uint64_t ref_table_id, ObStatConverterInfo& stat_converter_info)
{
int ret = OB_SUCCESS;
ObArray<uint64_t> column_ids;
if (OB_FAIL(init_vt_converter(tenant_id, ref_table_id, column_ids, stat_converter_info))) {
LOG_WARN("failed to init vt convert", K(ret));
}
return ret;
}
int ObTableColStatSqlService::init_vt_converter(uint64_t tenant_id, uint64_t ref_table_id,
const ObIArray<uint64_t>& column_ids, ObStatConverterInfo& stat_converter_info)
{
int ret = OB_SUCCESS;
const uint64_t real_table_id = ObSchemaUtils::get_real_table_mappings_tid(ref_table_id);
if (OB_INVALID_ID == real_table_id) {
} else {
share::schema::ObSchemaGetterGuard schema_guard;
const ObTableSchema* real_table_schema = NULL;
const ObTableSchema* vt_table_schema = NULL;
stat_converter_info.is_vt_mapping_ = true;
stat_converter_info.real_table_id_ = real_table_id;
bool has_column = (0 < column_ids.count());
if (!has_column) {
} else if (OB_ISNULL(GCTX.schema_service_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("schema_service is null", K(ret));
} else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(tenant_id, stat_converter_info.schema_guard_))) {
LOG_WARN("fail to get schema guard", K(ret));
} else if (OB_FAIL(stat_converter_info.schema_guard_.get_table_schema(
stat_converter_info.real_table_id_, real_table_schema))) {
LOG_WARN("get table schema failed", K(stat_converter_info.real_table_id_), K(ret));
} else if (OB_FAIL(stat_converter_info.schema_guard_.get_table_schema(ref_table_id, vt_table_schema))) {
LOG_WARN("get table schema failed", K(ref_table_id), K(ret));
} else if (OB_ISNULL(real_table_schema) || OB_ISNULL(vt_table_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("table schema is null", KP(real_table_schema), KP(vt_table_schema), K(ret));
} else if (OB_FAIL(get_mapping_columns_info(vt_table_schema, real_table_schema, column_ids, stat_converter_info))) {
LOG_WARN("failed to get mapping columns info", K(ret));
} else if (OB_FAIL(stat_converter_info.vt_result_converter_.init_without_allocator(stat_converter_info.col_schemas_,
&stat_converter_info.output_column_with_tenant_ids_,
tenant_id,
stat_converter_info.tenant_id_col_id_,
stat_converter_info.use_real_tenant_id_))) {
LOG_WARN("failed to init converter", K(ret));
}
if (OB_FAIL(ret)) {
} else {
LOG_DEBUG("debug virtual table stat",
K(stat_converter_info.real_table_id_),
K(tenant_id),
K(column_ids),
K(stat_converter_info.real_table_id_));
}
}
return ret;
}
int ObTableColStatSqlService::get_mapping_columns_info(const ObTableSchema* vt_table_schema,
const ObTableSchema* real_table_schema, const ObIArray<uint64_t>& column_ids,
ObStatConverterInfo& stat_converter_info)
{
int ret = OB_SUCCESS;
ObIArray<bool>& key_with_tenant_ids = stat_converter_info.output_column_with_tenant_ids_;
OZ(key_with_tenant_ids.reserve(column_ids.count()));
OZ(stat_converter_info.col_schemas_.reserve(column_ids.count()));
OZ(stat_converter_info.real_column_ids_.reserve(column_ids.count()));
OZ(stat_converter_info.column_ids_.assign(column_ids));
VTMapping* vt_mapping = nullptr;
get_real_table_vt_mapping(vt_table_schema->get_table_id(), vt_mapping);
if (OB_ISNULL(vt_mapping)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected status: vt mapping is null", K(ret), "table id", vt_table_schema->get_table_id());
}
for (int64_t k = 0; k < column_ids.count() && OB_SUCC(ret); ++k) {
uint64_t real_column_id = UINT64_MAX;
uint64_t vt_column_id = column_ids.at(k);
const ObColumnSchemaV2* vt_col_schema = vt_table_schema->get_column_schema(vt_column_id);
if (OB_ISNULL(vt_col_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected status: column schema is null", K(vt_column_id), K(ret));
}
for (int64_t nth_col = 0; nth_col < real_table_schema->get_column_count() && OB_SUCC(ret); ++nth_col) {
const ObColumnSchemaV2* real_col_schema = real_table_schema->get_column_schema_by_idx(nth_col);
if (OB_ISNULL(real_col_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("column schema is null", K(ret), K(nth_col));
} else if (0 == real_col_schema->get_column_name_str().case_compare(vt_col_schema->get_column_name_str())) {
real_column_id = real_col_schema->get_column_id();
bool extra_tenant_id = false;
for (int64_t nth_i = vt_mapping->start_pos_; !extra_tenant_id && nth_i < vt_mapping->end_pos_ && OB_SUCC(ret);
++nth_i) {
if (0 == ObString(with_tenant_id_columns[nth_i]).case_compare(vt_col_schema->get_column_name_str())) {
extra_tenant_id = true;
break;
}
}
OZ(key_with_tenant_ids.push_back(extra_tenant_id));
OZ(stat_converter_info.col_schemas_.push_back(vt_col_schema));
OZ(stat_converter_info.real_column_ids_.push_back(real_col_schema->get_column_id()));
if (0 == real_col_schema->get_column_name_str().case_compare(ObString("TENANT_ID"))) {
stat_converter_info.tenant_id_col_id_ = vt_column_id;
}
break;
}
}
if (OB_FAIL(ret)) {
} else if (UINT64_MAX == real_column_id) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected status: column not found", K(ret), K(vt_column_id), K(k));
}
}
if (OB_SUCC(ret)) {
stat_converter_info.use_real_tenant_id_ = vt_mapping->use_real_tenant_id_;
}
return ret;
}
int ObTableColStatSqlService::fetch_column_stat(const ObColumnStat::Key& key, ObColumnStat& stat)
{
int ret = OB_SUCCESS;
DEFINE_SQL_CLIENT_RETRY_WEAK_FOR_STAT(mysql_proxy_);
SMART_VAR(ObMySQLProxy::MySQLResult, res)
{
sqlclient::ObMySQLResult* result = NULL;
ObSqlString sql;
ObStatConverterInfo stat_converter_info;
const uint64_t tenant_id = extract_tenant_id(key.table_id_);
const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id);
if (!inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "sql service has not initialized.", K(ret));
} else if (!key.is_valid()) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "invalid arguments.", K(key), K(ret));
} else if (OB_FAIL(init_vt_converter(tenant_id, key.table_id_, key.column_id_, stat_converter_info))) {
COMMON_LOG(WARN, "fail to init virtual table converter.", K(key), K(ret));
} else if (OB_FAIL(sql.append(MY_FETCH_COL_STAT_SQL))) {
COMMON_LOG(WARN, "fail to append SQL stmt string.", K(MY_FETCH_COL_STAT_SQL), K(ret));
} else if (!stat_converter_info.is_vt_mapping_ &&
OB_FAIL(sql.append_fmt(" WHERE ((TENANT_ID=%lu AND TABLE_ID=%ld) OR (TENANT_ID=%lu AND TABLE_ID=%ld))"
" AND PARTITION_ID=%ld AND COLUMN_ID=%ld ORDER BY TENANT_ID",
ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id),
ObSchemaUtils::get_extract_schema_id(exec_tenant_id, key.table_id_),
tenant_id,
key.table_id_,
key.partition_id_,
key.column_id_))) {
COMMON_LOG(WARN, "fail to append SQL where string.", K(MY_FETCH_COL_STAT_SQL), K(ret));
} else if (stat_converter_info.is_vt_mapping_ &&
OB_FAIL(sql.append_fmt(" WHERE ((TENANT_ID=%lu AND TABLE_ID=%ld) OR (TENANT_ID=%lu AND TABLE_ID=%ld))"
" AND PARTITION_ID=%ld AND COLUMN_ID=%ld ORDER BY TENANT_ID",
ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id),
ObSchemaUtils::get_extract_schema_id(exec_tenant_id, stat_converter_info.real_table_id_),
tenant_id,
stat_converter_info.real_table_id_,
key.partition_id_,
stat_converter_info.real_column_ids_.at(0)))) {
COMMON_LOG(WARN, "fail to append SQL where string.", K(MY_FETCH_COL_STAT_SQL), K(ret));
} else if (OB_FAIL(sql_client_retry_weak.read(res, exec_tenant_id, sql.ptr()))) {
COMMON_LOG(WARN, "execute sql failed", "sql", sql.ptr(), K(ret));
} else if (NULL == (result = res.get_result())) {
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN, "fail to execute ", "sql", sql.ptr(), K(ret));
} else if (OB_FAIL(result->next())) {
if (OB_ITER_END != ret) {
COMMON_LOG(WARN, "result next failed, ", K(key), K(ret));
} else {
ret = OB_ENTRY_NOT_EXIST;
}
} else if (OB_FAIL(fill_column_stat(key.table_id_, *result, stat, 0, stat_converter_info))) {
COMMON_LOG(WARN, "read stat from result failed. ", K(key), K(ret));
} else {
COMMON_LOG(INFO, "succeed to get column stat", K(stat));
}
}
return ret;
}
int ObTableColStatSqlService::fetch_table_stat(
const common::ObPartitionKey& key, ObIArray<std::pair<ObPartitionKey, ObTableStat>>& all_part_stats)
{
int ret = OB_SUCCESS;
DEFINE_SQL_CLIENT_RETRY_WEAK_FOR_STAT(mysql_proxy_);
SMART_VAR(ObMySQLProxy::MySQLResult, res)
{
sqlclient::ObMySQLResult* result = NULL;
ObSqlString sql;
const char* table_name = NULL;
uint64_t exec_tenant_id = OB_SYS_TENANT_ID;
all_part_stats.reset();
ObStatConverterInfo stat_converter_info;
if (!inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "sql service has not initialized.", K(ret));
} else if (!key.is_valid()) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "invalid arguments.", K(key), K(ret));
} else {
if (is_sys_table(key.get_table_id())) {
table_name = oceanbase::share::OB_ALL_ROOT_TABLE_TNAME;
exec_tenant_id = OB_SYS_TENANT_ID;
} else {
table_name = oceanbase::share::OB_ALL_TENANT_PARTITION_META_TABLE_TNAME;
exec_tenant_id = extract_tenant_id(key.get_table_id());
}
if (OB_FAIL(init_vt_converter(exec_tenant_id, key.table_id_, stat_converter_info))) {
COMMON_LOG(WARN, "fail to init virtual table converter.", K(key), K(ret));
} else if (OB_FAIL(
sql.append_fmt("SELECT partition_id, data_version,row_count,data_size FROM %s ", table_name))) {
COMMON_LOG(WARN, "fail to append SQL stmt string.", K(sql), K(ret));
} else if (!stat_converter_info.is_vt_mapping_ &&
OB_FAIL(sql.append_fmt(" WHERE TENANT_ID = %ld AND TABLE_ID=%ld AND REPLICA_TYPE = 0 AND STATUS = "
"'REPLICA_STATUS_NORMAL' ORDER BY data_version DESC",
common::extract_tenant_id(key.get_table_id()),
key.get_table_id()))) {
COMMON_LOG(WARN, "fail to append SQL where string.", K(MY_FETCH_COL_STAT_SQL), K(ret));
} else if (stat_converter_info.is_vt_mapping_ &&
OB_FAIL(sql.append_fmt(" WHERE TENANT_ID = %ld AND TABLE_ID=%ld AND REPLICA_TYPE = 0 AND STATUS = "
"'REPLICA_STATUS_NORMAL' ORDER BY data_version DESC",
exec_tenant_id,
stat_converter_info.real_table_id_))) {
COMMON_LOG(WARN, "fail to append SQL where string.", K(MY_FETCH_COL_STAT_SQL), K(ret));
} else if (OB_FAIL(sql_client_retry_weak.read(res, exec_tenant_id, sql.ptr()))) {
COMMON_LOG(WARN, "execute sql failed", "sql", sql.ptr(), K(ret));
} else if (NULL == (result = res.get_result())) {
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN, "fail to execute ", "sql", sql.ptr(), K(ret));
}
while (OB_SUCC(ret)) {
int64_t partition_id = OB_INVALID_ID;
std::pair<ObPartitionKey, ObTableStat> part_stat;
if (OB_FAIL(result->next())) {
if (OB_ITER_END != ret) {
COMMON_LOG(WARN, "result next failed.", K(ret));
} else if (all_part_stats.empty()) {
ret = OB_ENTRY_NOT_EXIST;
} else {
ret = OB_SUCCESS;
break;
}
} else if (OB_FAIL(fill_table_stat(*result, partition_id, part_stat.second))) {
COMMON_LOG(WARN, "read stat from result failed. ", K(ret));
} else if (OB_FAIL(part_stat.first.init(key.get_table_id(), partition_id, key.get_partition_cnt()))) {
LOG_WARN("failed to init partition key", K(ret));
} else if (OB_FAIL(all_part_stats.push_back(part_stat))) {
LOG_WARN("failed to push back partition stats", K(ret));
}
}
}
}
return ret;
}
int ObTableColStatSqlService::fetch_batch_stat(const uint64_t table_id, const ObIArray<uint64_t>& partition_id,
const ObIArray<uint64_t>& column_id, ObIAllocator& allocator, common::ObIArray<ObColumnStat*>& stats,
const bool use_pure_id)
{
int ret = OB_SUCCESS;
DEFINE_SQL_CLIENT_RETRY_WEAK_FOR_STAT(mysql_proxy_);
SMART_VAR(ObMySQLProxy::MySQLResult, res)
{
sqlclient::ObMySQLResult* result = NULL;
ObSqlString sql;
stats.reuse();
ObStatConverterInfo stat_converter_info;
const uint64_t tenant_id = extract_tenant_id(table_id);
const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id);
if (!inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "sql service has not initialized.", K(ret));
} else if (OB_INVALID_ID == table_id) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "invalid argument.", K(ret), K(table_id), K(partition_id));
} else if (OB_UNLIKELY(partition_id.empty() || column_id.empty())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("column stat entry size is invalid", K(ret), K(partition_id.count()), K(column_id.count()));
} else if (OB_FAIL(init_vt_converter(tenant_id, table_id, column_id, stat_converter_info))) {
COMMON_LOG(WARN, "fail to init virtual table converter.", K(ret));
} else if (OB_FAIL(sql.append(MY_FETCH_COL_STAT_SQL))) {
COMMON_LOG(WARN, "fail to append SQL stmt string.", K(ret), K(MY_FETCH_COL_STAT_SQL));
} else if (!stat_converter_info.is_vt_mapping_ &&
OB_FAIL(sql.append_fmt(" WHERE TENANT_ID=%lu AND TABLE_ID = %ld AND PARTITION_ID IN ",
use_pure_id ? ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id) : tenant_id,
use_pure_id ? ObSchemaUtils::get_extract_schema_id(exec_tenant_id, table_id) : table_id))) {
COMMON_LOG(WARN, "fail to append SQL where string.", K(ret), K(MY_FETCH_COL_STAT_SQL));
} else if (stat_converter_info.is_vt_mapping_ &&
OB_FAIL(sql.append_fmt(" WHERE TENANT_ID=%lu AND TABLE_ID = %ld AND PARTITION_ID IN ",
use_pure_id ? ObSchemaUtils::get_extract_tenant_id(exec_tenant_id, tenant_id) : tenant_id,
use_pure_id
? ObSchemaUtils::get_extract_schema_id(exec_tenant_id, stat_converter_info.real_table_id_)
: stat_converter_info.real_table_id_))) {
COMMON_LOG(WARN, "fail to append SQL where string.", K(ret), K(MY_FETCH_COL_STAT_SQL));
}
for (int64_t i = 0; OB_SUCC(ret) && i < partition_id.count(); ++i) {
if (OB_FAIL(sql.append_fmt(
"%c%lu%c", (i == 0 ? '(' : ' '), partition_id.at(i), (i < partition_id.count() - 1 ? ',' : ')')))) {
COMMON_LOG(WARN, "fail to append SQL in string. ", K(ret), K(i));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(sql.append_fmt(" AND COLUMN_ID IN "))) {
COMMON_LOG(WARN, "fail to append column id filter.", K(ret), K(MY_FETCH_COL_STAT_SQL));
}
}
if (!stat_converter_info.is_vt_mapping_) {
for (int64_t i = 0; OB_SUCC(ret) && i < column_id.count(); ++i) {
if (OB_FAIL(sql.append_fmt(
"%c%lu%c", (i == 0 ? '(' : ' '), column_id.at(i), (i < column_id.count() - 1 ? ',' : ')')))) {
COMMON_LOG(WARN, "fail to append SQL in string", K(ret), K(i));
}
}
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < stat_converter_info.real_column_ids_.count(); ++i) {
if (OB_FAIL(sql.append_fmt("%c%lu%c",
(i == 0 ? '(' : ' '),
stat_converter_info.real_column_ids_.at(i),
(i < stat_converter_info.real_column_ids_.count() - 1 ? ',' : ')')))) {
COMMON_LOG(WARN, "fail to append SQL in string", K(ret), K(i));
}
}
}
if (OB_SUCC(ret)) {
void* tmp_ptr = NULL;
ObColumnStat* column_stat = NULL;
if (OB_FAIL(sql_client_retry_weak.read(res, exec_tenant_id, sql.ptr()))) {
COMMON_LOG(WARN, "execute sql failed", "sql", sql.ptr(), K(ret));
} else if (NULL == (result = res.get_result())) {
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN, "fail to execute ", "sql", sql.ptr(), K(ret));
} else {
int64_t idx = 0;
while (OB_SUCC(ret)) {
if (OB_FAIL(result->next())) {
if (OB_ITER_END != ret) {
COMMON_LOG(WARN, "result next failed.", K(ret));
} else if (stats.empty()) {
ret = OB_ENTRY_NOT_EXIST;
} else {
ret = OB_SUCCESS;
break;
}
} else if (OB_ISNULL(tmp_ptr = allocator.alloc(sizeof(ObColumnStat))) ||
OB_ISNULL(column_stat = new (tmp_ptr) ObColumnStat(allocator)) ||
OB_UNLIKELY(!column_stat->is_writable())) {
ret = OB_ALLOCATE_MEMORY_FAILED;
COMMON_LOG(ERROR, "failed to allocate memory for ObColumnStat", K(ret), "size", sizeof(ObColumnStat));
} else if (OB_FAIL(fill_column_stat(table_id, *result, *column_stat, idx, stat_converter_info))) {
COMMON_LOG(WARN, "read stat from result failed. ", K(ret), K(table_id), K(partition_id));
} else if (OB_FAIL(stats.push_back(column_stat))) {
LOG_WARN("failed to push back column stat", K(ret));
} else {
#if !defined(NDEBUG)
COMMON_LOG(INFO, "succeed to get column stat", K(*column_stat));
#endif
tmp_ptr = NULL;
column_stat = NULL;
++idx;
}
}
}
}
}
return ret;
}
int ObTableColStatSqlService::insert_or_update_column_stats(const ObIArray<ObColumnStat*>& stats)
{
int ret = OB_SUCCESS;
ObMySQLTransaction trans;
ObSqlString sql;
ObSqlString values;
share::ObDMLSqlSplicer dml;
ObArenaAllocator arean(ObModIds::OB_BUFFER);
int64_t affected_rows = 0;
uint64_t tenant_id = OB_INVALID_TENANT_ID;
if (!inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "sql service has not initialized.", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < stats.count(); ++i) {
dml.reuse();
if (NULL == stats.at(i)) {
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN, "item in stats must not NULL, ", K(ret), K(i));
} else if (OB_INVALID_TENANT_ID != tenant_id && tenant_id != extract_tenant_id(stats.at(i)->get_table_id())) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("update column stats with multi tenant not supported", K(ret), K(tenant_id), KPC(stats.at(i)));
} else if (OB_FAIL(fill_dml_splicer(*stats.at(i), dml))) {
COMMON_LOG(WARN, "fill add ObColumnStat stat.", K(ret), K(i), K(*stats.at(i)));
} else {
tenant_id = extract_tenant_id(stats.at(i)->get_table_id());
if (0 == i) {
if (OB_FAIL(dml.splice_column_names(values))) {
COMMON_LOG(WARN, "fail to splice column names.", K(ret));
} else if (OB_FAIL(sql.assign_fmt("INSERT /*+ use_plan_cache(none) */ INTO %s (%s) VALUES",
USER_TAB_COL_STATISTICS,
values.ptr()))) {
COMMON_LOG(WARN, "fail to assign sql string.", K(ret));
}
}
}
if (OB_SUCC(ret)) {
values.reset();
if (OB_FAIL(dml.splice_values(values))) {
COMMON_LOG(WARN, "fail to splice values.", K(ret));
} else if (OB_FAIL(sql.append_fmt("%s(%s)", 0 == i ? " " : " , ", values.ptr()))) {
COMMON_LOG(WARN, "fail to assign sql string.", K(ret));
} else {
if ((stats.count() - 1) == i) {
if (OB_FAIL(sql.append(" ON DUPLICATE KEY UPDATE "))) {
COMMON_LOG(WARN, "fail to append sql string.", K(ret));
} else if (OB_FAIL(sql.append(" version = values(version)")) ||
OB_FAIL(sql.append(", last_rebuild_version = values(last_rebuild_version)")) ||
OB_FAIL(sql.append(", num_distinct = values(num_distinct)")) ||
OB_FAIL(sql.append(", num_null = values(num_null)")) ||
OB_FAIL(sql.append(", min_value = values(min_value)")) ||
OB_FAIL(sql.append(", max_value = values(max_value)")) ||
OB_FAIL(sql.append(", llc_bitmap = values(llc_bitmap)")) ||
OB_FAIL(sql.append(", llc_bitmap_size = values(llc_bitmap_size)"))) {
COMMON_LOG(WARN, "fail to append sql string.", K(ret));
}
}
}
}
}
}
if (OB_SUCC(ret)) {
const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id);
if (OB_FAIL(trans.start(mysql_proxy_))) {
COMMON_LOG(WARN, "fail to start transaction. ", K(ret));
} else if (OB_FAIL(mysql_proxy_->write(exec_tenant_id, sql.ptr(), affected_rows))) {
COMMON_LOG(WARN, "fail to exec sql. ", K(ret), K(tenant_id));
} else if (affected_rows > 2 * stats.count()) {
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN,
"unexpected affected rows.",
K(ret),
"expect_affect_rows",
stats.count(),
"actual_affect_rows",
affected_rows);
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(trans.end(true))) {
COMMON_LOG(WARN, "fail to commit transacrion.", K(ret));
}
} else {
int tmp_ret = OB_SUCCESS;
if (OB_SUCCESS != (tmp_ret = trans.end(false))) {
COMMON_LOG(WARN, "fail to rollback transaction. ", K(tmp_ret));
}
}
return ret;
}
// replace into statement is not supported for now, use dml splice (insert_or_update) as substitution.
int ObTableColStatSqlService::insert_or_update_column_stat(const ObColumnStat& stat)
{
int ret = OB_SUCCESS;
const uint64_t tenant_id = extract_tenant_id(stat.get_table_id());
const uint64_t exec_tenant_id = ObSchemaUtils::get_exec_tenant_id(tenant_id);
ObMySQLTransaction trans;
share::ObDMLSqlSplicer dml;
share::ObDMLExecHelper dml_exec_helper(*mysql_proxy_, exec_tenant_id);
// TODO min,max value could be very large??
ObArenaAllocator arena(ObModIds::OB_BUFFER);
const int64_t total_buffer_size = stat.get_min_value().get_serialize_size() * 3 +
stat.get_min_value().get_serialize_size() * 3 + stat.get_llc_bitmap_size() * 2 +
3; // (2 bytes for c string end \0);
int64_t pos = 0;
int64_t min_value_str_pos = 0;
int64_t max_value_str_pos = 0;
int64_t llc_str_pos = 0;
int64_t affected_rows = 0;
int64_t llc_comp_size = 0;
char* all_field_buf = NULL;
char* llc_comp_buf = NULL;
if (!inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "sql service has not initialized.", K(ret));
} else if (!stat.is_valid()) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "invalid arguments.", K(stat), K(ret));
} else if (NULL == (all_field_buf = static_cast<char*>(arena.alloc(total_buffer_size)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
COMMON_LOG(ERROR, "cannot allocate memory.", K(total_buffer_size), K(ret));
} else if (OB_FAIL(serialize_to_hex_cstr(
stat.get_min_value(), all_field_buf, total_buffer_size, pos, min_value_str_pos))) {
COMMON_LOG(WARN, "serialize min obj value failed.", K(ret));
} else if (OB_FAIL(serialize_to_hex_cstr(
stat.get_max_value(), all_field_buf, total_buffer_size, pos, max_value_str_pos))) {
COMMON_LOG(WARN, "serialize max obj value failed.", K(ret));
} else if (OB_FAIL(get_compressed_llc_bitmap(
arena, stat.get_llc_bitmap(), stat.get_llc_bitmap_size(), llc_comp_buf, llc_comp_size))) {
COMMON_LOG(WARN, "get_compressed_llc_bitmap failed.", K(ret));
} else if (OB_FAIL(common::to_hex_cstr(
llc_comp_buf, llc_comp_size, all_field_buf, total_buffer_size, pos, llc_str_pos))) {
COMMON_LOG(WARN, "serialize llc bitmap failed.", K(llc_comp_size), K(ret));
} else {
if (OB_FAIL(dml.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))) ||
OB_FAIL(dml.add_pk_column("table_id", ObSchemaUtils::get_extract_schema_id(tenant_id, stat.get_table_id()))) ||
OB_FAIL(dml.add_pk_column("partition_id", stat.get_partition_id())) ||
OB_FAIL(dml.add_pk_column("column_id", stat.get_column_id())) ||
OB_FAIL(dml.add_column("version", stat.get_version())) ||
OB_FAIL(dml.add_column("last_rebuild_version", stat.get_last_rebuild_version())) ||
OB_FAIL(dml.add_column("num_distinct", stat.get_num_distinct())) ||
OB_FAIL(dml.add_column("num_null", stat.get_num_null())) ||
OB_FAIL(dml.add_column("min_value", all_field_buf + min_value_str_pos)) ||
OB_FAIL(dml.add_column("max_value", all_field_buf + max_value_str_pos)) ||
OB_FAIL(dml.add_column("llc_bitmap", all_field_buf + llc_str_pos)) ||
OB_FAIL(dml.add_column("llc_bitmap_size", llc_comp_size * 2))) {
COMMON_LOG(WARN, "add column failed", K(ret));
} else if (OB_FAIL(trans.start(mysql_proxy_))) {
COMMON_LOG(WARN, "fail to to start transaction. ", K(ret));
} else if (OB_FAIL(dml_exec_helper.exec_insert_update(USER_TAB_COL_STATISTICS, dml, affected_rows))) {
COMMON_LOG(WARN, "fail to to write transaction. ", K(ret));
} else if (affected_rows > 2) {
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN, "replace into return grate than 2", K(affected_rows), K(ret));
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(trans.end(true))) {
COMMON_LOG(WARN, "fail to commit transaction.", K(ret));
}
} else {
int tmp_ret = OB_SUCCESS;
if (OB_SUCCESS != (tmp_ret = trans.end(false))) {
COMMON_LOG(WARN, "fail to rollback transaction. ", K(tmp_ret));
}
}
return ret;
}
int ObTableColStatSqlService::fill_column_stat(const uint64_t table_id, common::sqlclient::ObMySQLResult& result,
ObColumnStat& stat, int64_t idx, ObStatConverterInfo& stat_converter_info)
{
int ret = OB_SUCCESS;
uint64_t dummy = 0;
if (!inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "sql service has not initialized.", K(ret));
}
// after 2.2.4 __all_column_statistic stores pure table id (without tenant_id)
// the stat cache stores full table id (with tenant_id)
stat.set_table_id(table_id);
EXTRACT_INT_FIELD_MYSQL(result, "tenant_id", dummy, uint64_t);
EXTRACT_INT_FIELD_MYSQL(result, "table_id", dummy, uint64_t);
EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, partition_id, stat, uint64_t);
EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, column_id, stat, uint64_t);
EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, version, stat, int64_t);
EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, last_rebuild_version, stat, int64_t);
EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, num_distinct, stat, int64_t);
EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, num_null, stat, int64_t);
ObArenaAllocator arena(ObModIds::OB_BUFFER);
char* bitmap_buf = NULL;
ObString str_field;
EXTRACT_VARCHAR_FIELD_MYSQL(result, "llc_bitmap", str_field);
if (OB_SUCC(ret)) {
if (NULL == (bitmap_buf = static_cast<char*>(arena.alloc(str_field.length())))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
COMMON_LOG(ERROR, "allocate memory for llc_bitmap failed.", K(str_field.length()), K(ret));
} else {
common::str_to_hex(str_field.ptr(), str_field.length(), bitmap_buf, str_field.length());
}
}
if (OB_SUCC(ret)) {
// decompress llc bitmap;
char* decomp_buf = NULL;
int64_t decomp_size = ObColumnStat::NUM_LLC_BUCKET;
const int64_t bitmap_size = str_field.length() / 2;
if (OB_FAIL(get_decompressed_llc_bitmap(arena, bitmap_buf, bitmap_size, decomp_buf, decomp_size))) {
COMMON_LOG(WARN, "decompress bitmap buffer failed.", K(ret));
} else if (OB_FAIL(stat.store_llc_bitmap(decomp_buf, decomp_size))) {
COMMON_LOG(
WARN, "set llc bitmap failed.", KP(bitmap_buf), K(bitmap_size), KP(decomp_buf), K(decomp_size), K(ret));
}
}
common::ObObj obj;
EXTRACT_VARCHAR_FIELD_MYSQL(result, "min_value", str_field);
if (OB_SUCC(ret)) {
if (stat_converter_info.is_vt_mapping_ && idx >= stat_converter_info.column_ids_.count()) {
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN,
"unexpected status: column idx is invalid",
K(ret),
"column count",
stat_converter_info.column_ids_.count(),
"column idx",
idx);
} else if (OB_FAIL(deserialize_hex_cstr(str_field.ptr(), str_field.length(), arena, obj))) {
COMMON_LOG(WARN, "deserialize_hex_cstr min value failed.", K(stat), K(ret));
} else if (stat_converter_info.is_vt_mapping_ && OB_FAIL(stat_converter_info.vt_result_converter_.convert_column(
obj, stat_converter_info.column_ids_.at(idx), idx))) {
} else if (OB_FAIL(stat.store_min_value(obj))) {
COMMON_LOG(WARN, "store min value failed.", K(stat), K(ret));
}
}
EXTRACT_VARCHAR_FIELD_MYSQL(result, "max_value", str_field);
if (OB_SUCC(ret)) {
if (stat_converter_info.is_vt_mapping_ && idx >= stat_converter_info.column_ids_.count()) {
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN,
"unexpected status: column idx is invalid",
K(ret),
"column count",
stat_converter_info.column_ids_.count(),
"column idx",
idx);
} else if (OB_FAIL(deserialize_hex_cstr(str_field.ptr(), str_field.length(), arena, obj))) {
COMMON_LOG(WARN, "deserialize_hex_cstr max value failed.", K(stat), K(ret));
} else if (stat_converter_info.is_vt_mapping_ && OB_FAIL(stat_converter_info.vt_result_converter_.convert_column(
obj, stat_converter_info.column_ids_.at(idx), idx))) {
} else if (OB_FAIL(stat.store_max_value(obj))) {
COMMON_LOG(WARN, "store max value failed.", K(stat), K(ret));
}
}
UNUSED(dummy);
return ret;
}
int ObTableColStatSqlService::fill_table_stat(
common::sqlclient::ObMySQLResult& result, int64_t& part_id, ObTableStat& stat)
{
int ret = OB_SUCCESS;
if (!inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "sql service has not initialized.", K(ret));
}
EXTRACT_INT_FIELD_MYSQL(result, "partition_id", part_id, int64_t);
EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, data_version, stat, int64_t);
EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, row_count, stat, int64_t);
EXTRACT_INT_FIELD_TO_CLASS_MYSQL(result, data_size, stat, int64_t);
if (OB_SUCC(ret)) {
if (stat.get_row_count() > 0) {
stat.set_average_row_size(stat.get_data_size() / stat.get_row_count());
}
}
return ret;
}
int ObTableColStatSqlService::serialize_to_hex_cstr(
const common::ObObj& obj, char* buf, int64_t buf_len, int64_t& pos, int64_t& cstr_pos)
{
int ret = OB_SUCCESS;
int64_t hex_len = 0;
int64_t start_pos = pos;
if (!inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "sql service has not initialized.", K(ret));
} else if (NULL == buf || buf_len < 0 || pos < 0) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "invalid arguments.", KP(buf), K(buf_len), K(pos), K(ret));
} else if (OB_FAIL(obj.serialize(buf, buf_len, pos))) {
COMMON_LOG(WARN, "serialize obj failed.", KP(buf), K(buf_len), K(pos), K(ret));
} else {
hex_len = pos - start_pos;
if (OB_FAIL(common::to_hex_cstr(buf + start_pos, hex_len, buf, buf_len, pos, cstr_pos))) {
COMMON_LOG(WARN, "Failed to transform to hex cstr", K(ret));
}
}
return ret;
}
int ObTableColStatSqlService::deserialize_hex_cstr(char* buf, int64_t buf_len, common::ObObj& obj)
{
int ret = OB_SUCCESS;
int64_t pos = 0;
int64_t ret_len = 0;
if (!inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "sql service has not initialized.", K(ret));
} else if (NULL == buf || buf_len < 0) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "invalid arguments.", KP(buf), K(buf_len), K(ret));
} else if (buf_len !=
(ret_len = common::str_to_hex(buf, static_cast<int32_t>(buf_len), buf, static_cast<int32_t>(buf_len)))) {
// str_to_hex can use input as output, convert char in placement.
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN, "transfer str to hex failed.", K(buf), K(buf_len), K(ret_len), K(ret));
} else if (OB_FAIL(obj.deserialize(buf, ret_len / 2, pos))) {
COMMON_LOG(WARN, "deserialize obj failed.", K(buf), K(buf_len), K(pos), K(ret));
}
return ret;
}
int ObTableColStatSqlService::deserialize_hex_cstr(
char* buf, int64_t buf_len, ObIAllocator& allocator, common::ObObj& obj)
{
int ret = OB_SUCCESS;
int64_t pos = 0;
int64_t ret_len = 0;
char* resbuf = NULL;
if (!inited_) {
ret = OB_NOT_INIT;
COMMON_LOG(WARN, "sql service has not initialized.", K(ret));
} else if (NULL == buf || buf_len < 0) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "invalid arguments.", KP(buf), K(buf_len), K(ret));
} else if (NULL == (resbuf = static_cast<char*>(allocator.alloc(buf_len)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
COMMON_LOG(ERROR, "cannot allocate memory for deserialize obj.", K(buf_len), K(ret));
} else if (buf_len != (ret_len = common::str_to_hex(
buf, static_cast<int32_t>(buf_len), resbuf, static_cast<int32_t>(buf_len)))) {
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN, "transfer str to hex failed.", K(buf), K(buf_len), K(ret_len), K(ret));
} else if (OB_FAIL(obj.deserialize(resbuf, ret_len, pos))) {
COMMON_LOG(WARN, "deserialize obj failed.", K(buf), K(buf_len), K(pos), K(ret));
}
return ret;
}
int ObTableColStatSqlService::get_compressed_llc_bitmap(
ObIAllocator& allocator, const char* bitmap_buf, int64_t bitmap_size, char*& comp_buf, int64_t& comp_size)
{
int ret = OB_SUCCESS;
ObCompressor* compressor = NULL;
int64_t max_comp_size = 0;
if (NULL == bitmap_buf || bitmap_size <= 0) {
ret = common::OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "invalid arguments.", KP(bitmap_buf), K(bitmap_size), K(ret));
} else if (OB_FAIL(ObCompressorPool::get_instance().get_compressor(bitmap_compress_lib_name, compressor))) {
COMMON_LOG(WARN, "cannot create compressor, do not compress data.", K(bitmap_compress_lib_name), K(ret));
} else if (NULL == compressor) {
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN, "compressor is NULL, do not compress data.", K(bitmap_compress_lib_name), K(ret));
} else if (OB_FAIL(compressor->get_max_overflow_size(bitmap_size, max_comp_size))) {
COMMON_LOG(WARN, "get max overflow size failed.", K(bitmap_compress_lib_name), K(bitmap_size), K(ret));
} else {
max_comp_size += bitmap_size;
if (NULL == (comp_buf = static_cast<char*>(allocator.alloc(max_comp_size)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
COMMON_LOG(ERROR, "cannot allocate compressed buffer.", K(max_comp_size), K(ret));
} else if (OB_FAIL(compressor->compress(bitmap_buf, bitmap_size, comp_buf, max_comp_size, comp_size))) {
COMMON_LOG(WARN, "compress llc bitmap failed.", K(ret));
} else if (comp_size >= bitmap_size) {
// compress is not work, just use original data.
comp_buf = const_cast<char*>(bitmap_buf);
comp_size = bitmap_size;
}
}
return ret;
}
int ObTableColStatSqlService::get_decompressed_llc_bitmap(
ObIAllocator& allocator, const char* comp_buf, int64_t comp_size, char*& bitmap_buf, int64_t& bitmap_size)
{
int ret = OB_SUCCESS;
const int64_t max_bitmap_size = ObColumnStat::NUM_LLC_BUCKET; // max size of uncompressed buffer.
ObCompressor* compressor = NULL;
if (comp_size >= ObColumnStat::NUM_LLC_BUCKET) {
// not compressed bitmap, use directly;
bitmap_buf = const_cast<char*>(comp_buf);
bitmap_size = comp_size;
} else if (NULL == (bitmap_buf = static_cast<char*>(allocator.alloc(max_bitmap_size)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
COMMON_LOG(ERROR, "allocate memory for uncompressed data failed.", K(max_bitmap_size), K(ret));
} else if (OB_FAIL(ObCompressorPool::get_instance().get_compressor(bitmap_compress_lib_name, compressor))) {
COMMON_LOG(WARN, "cannot create compressor, do not uncompress data.", K(bitmap_compress_lib_name), K(ret));
} else if (NULL == compressor) {
ret = OB_ERR_UNEXPECTED;
COMMON_LOG(WARN, "compressor is NULL, do not compress data.", K(bitmap_compress_lib_name), K(ret));
} else if (OB_FAIL(compressor->decompress(comp_buf, comp_size, bitmap_buf, max_bitmap_size, bitmap_size))) {
COMMON_LOG(WARN,
"decompress bitmap buffer failed.",
KP(comp_buf),
K(comp_size),
KP(bitmap_buf),
K(max_bitmap_size),
K(bitmap_size),
K(ret));
}
return ret;
}
int ObTableColStatSqlService::fill_dml_splicer(const ObColumnStat& stat, share::ObDMLSqlSplicer& dml_splicer)
{
int ret = OB_SUCCESS;
ObArenaAllocator arena(ObModIds::OB_BUFFER);
const int64_t total_buffer_size = stat.get_min_value().get_serialize_size() * 3 +
stat.get_min_value().get_serialize_size() * 3 + stat.get_llc_bitmap_size() * 2 + 3;
int64_t pos = 0;
int64_t min_value_str_pos = 0;
int64_t max_value_str_pos = 0;
int64_t llc_str_pos = 0;
int64_t llc_comp_size = 0;
char* all_field_buf = NULL;
char* llc_comp_buf = NULL;
if (!stat.is_valid()) {
ret = OB_INVALID_ARGUMENT;
COMMON_LOG(WARN, "invalid argument, ", K(ret), K(stat));
} else if (NULL == (all_field_buf = static_cast<char*>(arena.alloc(total_buffer_size)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
COMMON_LOG(ERROR, "cannot allocate memory.", K(ret), K(total_buffer_size));
} else if (OB_FAIL(serialize_to_hex_cstr(
stat.get_min_value(), all_field_buf, total_buffer_size, pos, min_value_str_pos))) {
COMMON_LOG(WARN, "serialize min obj value failed.", K(ret));
} else if (OB_FAIL(serialize_to_hex_cstr(
stat.get_max_value(), all_field_buf, total_buffer_size, pos, max_value_str_pos))) {
COMMON_LOG(WARN, "serialize max obj value failed.", K(ret));
} else if (OB_FAIL(get_compressed_llc_bitmap(
arena, stat.get_llc_bitmap(), stat.get_llc_bitmap_size(), llc_comp_buf, llc_comp_size))) {
COMMON_LOG(WARN, "get_compressed_llc_bitmap failed.", K(ret));
} else if (OB_FAIL(common::to_hex_cstr(
llc_comp_buf, llc_comp_size, all_field_buf, total_buffer_size, pos, llc_str_pos))) {
COMMON_LOG(WARN, "serialize llc bitmap failed.", K(ret), K(llc_comp_size));
} else {
const uint64_t tenant_id = extract_tenant_id(stat.get_table_id());
if (OB_FAIL(dml_splicer.add_pk_column("tenant_id", ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))) ||
OB_FAIL(dml_splicer.add_pk_column(
"table_id", ObSchemaUtils::get_extract_schema_id(tenant_id, stat.get_table_id()))) ||
OB_FAIL(dml_splicer.add_pk_column("partition_id", stat.get_partition_id())) ||
OB_FAIL(dml_splicer.add_pk_column("column_id", stat.get_column_id())) ||
OB_FAIL(dml_splicer.add_column("version", stat.get_version())) ||
OB_FAIL(dml_splicer.add_column("last_rebuild_version", stat.get_last_rebuild_version())) ||
OB_FAIL(dml_splicer.add_column("num_distinct", stat.get_num_distinct())) ||
OB_FAIL(dml_splicer.add_column("num_null", stat.get_num_null())) ||
OB_FAIL(dml_splicer.add_column("min_value", all_field_buf + min_value_str_pos)) ||
OB_FAIL(dml_splicer.add_column("max_value", all_field_buf + max_value_str_pos)) ||
OB_FAIL(dml_splicer.add_column("llc_bitmap", all_field_buf + llc_str_pos)) ||
OB_FAIL(dml_splicer.add_column("llc_bitmap_size", llc_comp_size * 2))) {
COMMON_LOG(WARN, "add column failed.", K(ret));
}
}
return ret;
}
} // end of namespace common
} // end of namespace oceanbase