Files
oceanbase/src/share/stat/ob_dbms_stats_maintenance_window.cpp

598 lines
30 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 "share/stat/ob_dbms_stats_maintenance_window.h"
#include "lib/timezone/ob_time_convert.h"
#include "lib/time/ob_time_utility.h"
#include "share/schema/ob_schema_utils.h"
#include "share/ob_dml_sql_splicer.h"
#include "share/inner_table/ob_inner_table_schema_constants.h"
#include "sql/session/ob_basic_session_info.h"
#include "observer/omt/ob_tenant_timezone_mgr.h"
#include "lib/timezone/ob_timezone_info.h"
#define ALL_TENANT_SCHEDULER_JOB_COLUMN_NAME "tenant_id, " \
"job_name, " \
"job, " \
"lowner, " \
"powner, " \
"cowner, " \
"next_date," \
"total," \
"`interval#`," \
"flag," \
"what," \
"nlsenv," \
"field1," \
"exec_env,"\
"job_style,"\
"program_name,"\
"job_type,"\
"job_action,"\
"number_of_argument,"\
"start_date,"\
"repeat_interval,"\
"end_date,"\
"job_class,"\
"enabled,"\
"auto_drop,"\
"comments,"\
"credential_name,"\
"destination_name,"\
"interval_ts,"\
"max_run_duration"
namespace oceanbase {
namespace common {
const char *windows_name[DAY_OF_WEEK] = {"MONDAY_WINDOW",
"TUESDAY_WINDOW",
"WEDNESDAY_WINDOW",
"THURSDAY_WINDOW",
"FRIDAY_WINDOW",
"SATURDAY_WINDOW",
"SUNDAY_WINDOW"};
const char *opt_stats_history_manager = "OPT_STATS_HISTORY_MANAGER";
int ObDbmsStatsMaintenanceWindow::get_stats_maintenance_window_jobs_sql(const ObSysVariableSchema &sys_variable,
const uint64_t tenant_id,
ObSqlString &raw_sql,
int64_t &expected_affected_rows)
{
int ret = OB_SUCCESS;
char buf[OB_MAX_PROC_ENV_LENGTH];
int64_t current_time = ObTimeUtility::current_time();
ObSqlString tmp_sql;
ObSqlString job_action;
int64_t job_id = 1;
int64_t pos = 0;
int32_t offset_sec = 0;
bool is_oracle_mode = false;
if (OB_FAIL(raw_sql.append_fmt("INSERT INTO %s( "ALL_TENANT_SCHEDULER_JOB_COLUMN_NAME") VALUES ",
share::OB_ALL_TENANT_SCHEDULER_JOB_TNAME))) {
LOG_WARN("failed to append fmt", K(ret));
} else if (OB_FAIL(sys_variable.get_oracle_mode(is_oracle_mode))) {
LOG_WARN("failed to get oracle mode", K(ret));
} else if (OB_FAIL(sql::ObExecEnv::gen_exec_env(sys_variable, buf, OB_MAX_PROC_ENV_LENGTH, pos))) {
LOG_WARN("failed to gen exec env", K(ret));
} else if (OB_FAIL(get_time_zone_offset(sys_variable, tenant_id, offset_sec))) {
LOG_WARN("failed to get time zone offset", K(ret));
} else {
ObString exec_env(pos, buf);
//current_time = current_time + offset_sec * 1000000;
for (int64_t i = 0; i < DAY_OF_WEEK; ++i) {
tmp_sql.reset();
int64_t start_usec = -1;
ObSqlString job_action;
if (OB_FAIL(get_window_job_info(current_time, i + 1, offset_sec, start_usec, job_action))) {
LOG_WARN("failed to get window job info", K(ret));
} else if (OB_UNLIKELY(start_usec == -1 || job_action.empty())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(start_usec), K(job_action));
} else {
if (OB_FAIL(get_stat_window_job_sql(is_oracle_mode,
tenant_id,
job_id++,
windows_name[i],
exec_env,
start_usec,
job_action,
tmp_sql))) {
LOG_WARN("failed to get stat window job sql", K(ret));
} else if (OB_FAIL(raw_sql.append_fmt("%s(%s)", (i == 0 ? "" : ","), tmp_sql.ptr()))) {
LOG_WARN("failed to append sql", K(ret));
} else {
++ expected_affected_rows;
tmp_sql.reset();
job_action.reset();
if (OB_FAIL(get_stat_window_job_sql(is_oracle_mode,
tenant_id,
0,
windows_name[i],
exec_env,
start_usec,
job_action,
tmp_sql))) {
LOG_WARN("failed to get stat window job sql", K(ret));
} else if (OB_FAIL(raw_sql.append_fmt("%s(%s)", ",", tmp_sql.ptr()))) {
LOG_WARN("failed to append sql", K(ret));
} else {
++ expected_affected_rows;
tmp_sql.reset();
job_action.reset();
}
}
}
}
if (OB_SUCC(ret)) {
//set stats history manager job
if (OB_FAIL(get_stats_history_manager_job_sql(is_oracle_mode, tenant_id,
job_id++, exec_env, tmp_sql))) {
LOG_WARN("failed to get stats history manager job sql", K(ret));
} else if (OB_FAIL(raw_sql.append_fmt(", (%s)", tmp_sql.ptr()))) {
LOG_WARN("failed to append sql", K(ret));
} else {
++ expected_affected_rows;
tmp_sql.reset();
if (OB_FAIL(get_stats_history_manager_job_sql(is_oracle_mode, tenant_id,
0, exec_env, tmp_sql))) {
LOG_WARN("failed to get stats history manager job sql", K(ret));
} else if (OB_FAIL(raw_sql.append_fmt(", (%s)", tmp_sql.ptr()))) {
LOG_WARN("failed to append sql", K(ret));
} else {
++ expected_affected_rows;
tmp_sql.reset();
}
}
//set dummy guard job
if (OB_FAIL(ret)) {
} else if (OB_FAIL(get_dummy_guard_job_sql(tenant_id, job_id, tmp_sql))) {
LOG_WARN("failed to insert dummy guard job", K(ret));
} else if (OB_FAIL(raw_sql.append_fmt(", (%s);", tmp_sql.ptr()))) {
LOG_WARN("failed to append sql", K(ret));
} else {
++ expected_affected_rows;
LOG_INFO("succeed to get stats maintenance window job sql", K(raw_sql));
}
}
}
return ret;
}
int ObDbmsStatsMaintenanceWindow::get_stat_window_job_sql(const bool is_oracle_mode,
const uint64_t tenant_id,
const int64_t job_id,
const char *job_name,
const ObString &exec_env,
const int64_t start_usec,
ObSqlString &job_action,
ObSqlString &raw_sql)
{
int ret = OB_SUCCESS;
int64_t interval_ts = DEFAULT_WEEK_INTERVAL_USEC;
int64_t end_date = 64060560000000000;//4000-01-01 00:00:00.000000
int64_t default_duration_sec = is_work_day(job_id) ? DEFAULT_WORKING_DAY_DURATION_SEC : DEFAULT_NON_WORKING_DAY_DURATION_SEC;
share::ObDMLSqlSplicer dml;
OZ (dml.add_pk_column("tenant_id", share::schema::ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id)));
OZ (dml.add_column("job_name", ObHexEscapeSqlStr(ObString(job_name))));
OZ (dml.add_pk_column("job", job_id));
OZ (dml.add_column("lowner", is_oracle_mode ? ObHexEscapeSqlStr("SYS") : ObHexEscapeSqlStr("root")));
OZ (dml.add_column("powner", is_oracle_mode ? ObHexEscapeSqlStr("SYS") : ObHexEscapeSqlStr("root")));
OZ (dml.add_column("cowner", is_oracle_mode ? ObHexEscapeSqlStr("SYS") : ObHexEscapeSqlStr("oceanbase")));
OZ (dml.add_time_column("next_date", start_usec));
OZ (dml.add_column("total", 0));
OZ (dml.add_column("`interval#`", ObHexEscapeSqlStr(ObString("FREQ=WEEKLY; INTERVAL=1"))));
OZ (dml.add_column("flag", 0));
OZ (dml.add_column("what", ObHexEscapeSqlStr(job_action.string())));
OZ (dml.add_column("nlsenv", ObHexEscapeSqlStr(ObString(""))));
OZ (dml.add_column("field1", ObHexEscapeSqlStr(ObString(""))));
OZ (dml.add_column("exec_env", ObHexEscapeSqlStr(exec_env)));
OZ (dml.add_column("job_style", ObHexEscapeSqlStr(ObString("REGULER"))));
OZ (dml.add_column("program_name", ObHexEscapeSqlStr(ObString(""))));
OZ (dml.add_column("job_type", ObHexEscapeSqlStr(ObString("STORED_PROCEDURE"))));
OZ (dml.add_column("job_action", ObHexEscapeSqlStr(job_action.string())));
OZ (dml.add_column("number_of_argument", 0));
OZ (dml.add_time_column("start_date", start_usec));
OZ (dml.add_column("repeat_interval", ObHexEscapeSqlStr(ObString("FREQ=WEEKLY; INTERVAL=1"))));
OZ (dml.add_raw_time_column("end_date", end_date));
OZ (dml.add_column("job_class", ObHexEscapeSqlStr(ObString("DEFAULT_JOB_CLASS"))));
OZ (dml.add_column("enabled", true));
OZ (dml.add_column("auto_drop", false));
OZ (dml.add_column("comments", ObHexEscapeSqlStr(ObString("used to auto gather table stats"))));
OZ (dml.add_column("credential_name", ObHexEscapeSqlStr(ObString(""))));
OZ (dml.add_column("destination_name", ObHexEscapeSqlStr(ObString(""))));
OZ (dml.add_column("interval_ts", interval_ts));
OZ (dml.add_column("max_run_duration", default_duration_sec));
OZ (dml.splice_values(raw_sql));
return ret;
}
int ObDbmsStatsMaintenanceWindow::get_stats_history_manager_job_sql(const bool is_oracle_mode,
const uint64_t tenant_id,
const int64_t job_id,
const ObString &exec_env,
ObSqlString &raw_sql)
{
int ret = OB_SUCCESS;
int64_t interval_ts = DEFAULT_DAY_INTERVAL_USEC;
int64_t end_date = 64060560000000000;//4000-01-01 00:00:00.000000
int64_t current = ObTimeUtility::current_time() + DEFAULT_DAY_INTERVAL_USEC;
share::ObDMLSqlSplicer dml;
OZ (dml.add_pk_column("tenant_id", share::schema::ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id)));
OZ (dml.add_column("job_name", ObHexEscapeSqlStr(ObString(opt_stats_history_manager))));
OZ (dml.add_pk_column("job", job_id));
OZ (dml.add_column("lowner", is_oracle_mode ? ObHexEscapeSqlStr("SYS") : ObHexEscapeSqlStr("root")));
OZ (dml.add_column("powner", is_oracle_mode ? ObHexEscapeSqlStr("SYS") : ObHexEscapeSqlStr("root")));
OZ (dml.add_column("cowner", is_oracle_mode ? ObHexEscapeSqlStr("SYS") : ObHexEscapeSqlStr("oceanbase")));
OZ (dml.add_time_column("next_date", current));
OZ (dml.add_column("total", 0));
OZ (dml.add_column("`interval#`", ObHexEscapeSqlStr(ObString("FREQ=DAYLY; INTERVAL=1"))));
OZ (dml.add_column("flag", 0));
OZ (dml.add_column("what", ObHexEscapeSqlStr("DBMS_STATS.PURGE_STATS(NULL)")));
OZ (dml.add_column("nlsenv", ObHexEscapeSqlStr(ObString(""))));
OZ (dml.add_column("field1", ObHexEscapeSqlStr(ObString(""))));
OZ (dml.add_column("exec_env", ObHexEscapeSqlStr(exec_env)));
OZ (dml.add_column("job_style", ObHexEscapeSqlStr(ObString("REGULER"))));
OZ (dml.add_column("program_name", ObHexEscapeSqlStr(ObString(""))));
OZ (dml.add_column("job_type", ObHexEscapeSqlStr(ObString("STORED_PROCEDURE"))));
OZ (dml.add_column("job_action", ObHexEscapeSqlStr("DBMS_STATS.PURGE_STATS(NULL)")));
OZ (dml.add_column("number_of_argument", 0));
OZ (dml.add_raw_time_column("start_date", current));
OZ (dml.add_column("repeat_interval", ObHexEscapeSqlStr(ObString("FREQ=DAYLY; INTERVAL=1"))));
OZ (dml.add_raw_time_column("end_date", end_date));
OZ (dml.add_column("job_class", ObHexEscapeSqlStr(ObString("DEFAULT_JOB_CLASS"))));
OZ (dml.add_column("enabled", true));
OZ (dml.add_column("auto_drop", false));
OZ (dml.add_column("comments", ObHexEscapeSqlStr(ObString("used to stats history manager"))));
OZ (dml.add_column("credential_name", ObHexEscapeSqlStr(ObString(""))));
OZ (dml.add_column("destination_name", ObHexEscapeSqlStr(ObString(""))));
OZ (dml.add_column("interval_ts", interval_ts));
OZ (dml.add_column("max_run_duration", DEFAULT_HISTORY_MANAGER_DURATION_SEC));
OZ (dml.splice_values(raw_sql));
return ret;
}
//this dummy guard job is used to make sure the job id is monotonically increaseing
int ObDbmsStatsMaintenanceWindow::get_dummy_guard_job_sql(const uint64_t tenant_id,
const int64_t job_id,
ObSqlString &raw_sql)
{
int ret = OB_SUCCESS;
share::ObDMLSqlSplicer dml;
OZ (dml.add_pk_column("tenant_id", share::schema::ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id)));
OZ (dml.add_column("job_name", ObHexEscapeSqlStr(ObString("__dummy_guard"))));
OZ (dml.add_pk_column("job", job_id));
OZ (dml.add_column("lowner", ObHexEscapeSqlStr(ObString("SYS"))));
OZ (dml.add_column("powner", ObHexEscapeSqlStr(ObString("SYS"))));
OZ (dml.add_column("cowner", ObHexEscapeSqlStr(ObString("SYS"))));
OZ (dml.add_time_column("next_date", 0));
OZ (dml.add_column("total", 0));
OZ (dml.add_column("`interval#`", ObHexEscapeSqlStr(ObString("null"))));
OZ (dml.add_column("flag", 0));
OZ (dml.splice_values(raw_sql));
//column_name:
// what,nlsenv,field1,exec_env,job_style,program_name,job_type,job_action,number_of_argument,
// start_date,repeat_interval,end_date,job_class,enabled,auto_drop,comments,credential_name,
// destination_name,interval_ts
if (OB_SUCC(ret)) {
if (OB_FAIL(raw_sql.append(", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,"
"NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL"))) {
LOG_WARN("failed to append", K(ret));
}
}
return ret;
}
/* like Oracle, we set 7 windows:
* WINDOW_NAME REPEAT_INTERVAL DURATION
* MONDAY_WINDOW freq=daily;byday=MON;byhour=22; 4 hours
* TUESDAY_WINDOW freq=daily;byday=TUE;byhour=22; 4 hours
* WEDNESDAY_WINDOW freq=daily;byday=WED;byhour=22; 4 hours
* THURSDAY_WINDOW freq=daily;byday=THU;byhour=22; 4 hours
* FRIDAY_WINDOW freq=daily;byday=FRI;byhour=22; 4 hours
* SATURDAY_WINDOW freq=daily;byday=SAT;byhour=6; 20 hours
* SUNDAY_WINDOW freq=daily;byday=SUN;byhour=6; 20 hours
*
*/
int ObDbmsStatsMaintenanceWindow::get_window_job_info(const int64_t current_time,
const int64_t nth_window,
const int64_t offset_sec,
int64_t &start_usec,
ObSqlString &job_action)
{
int ret = OB_SUCCESS;
ObTime ob_time;
if (OB_UNLIKELY(nth_window < 1 || nth_window > DAYS_PER_WEEK || current_time <= 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(nth_window), K(current_time));
} else if (OB_FAIL(ObTimeConverter::usec_to_ob_time(current_time + offset_sec * 1000000,
ob_time))) {
LOG_WARN("failed to usec to ob time", K(ret), K(current_time), K(offset_sec));
} else if (OB_UNLIKELY(ob_time.parts_[DT_WDAY] < 1 ||
ob_time.parts_[DT_WDAY] > DAYS_PER_WEEK)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(ob_time.parts_[DT_WDAY]));
} else {
//work day set default start time is 22:00 and non-work day set default start time is 6:00
int64_t default_start_hour = is_work_day(nth_window) ? DEFAULT_WORKING_DAY_START_HOHR : DEFAULT_NON_WORKING_DAY_START_HOHR;
//work day set default duration time is 4 hours and non-work day set default duration time is 20 hours
int64_t default_duration_usec = is_work_day(nth_window) ? DEFAULT_WORKING_DAY_DURATION_USEC : DEFAULT_NON_WORKING_DAY_DURATION_USEC;
int64_t total_hour_with_trunc = current_time / USEC_OF_HOUR;
int64_t current_hour = ob_time.parts_[DT_HOUR];
int64_t current_wday = ob_time.parts_[DT_WDAY];
LOG_INFO("begin to get window job info", K(current_time), K(total_hour_with_trunc),
K(current_hour), K(current_wday), K(nth_window),
K(default_start_hour), K(default_duration_usec));
if (OB_FAIL(job_action.append_fmt("DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC(%ld)",
default_duration_usec))) {
LOG_WARN("failed to append", K(ret));
} else {
int64_t offset_day = nth_window - current_wday;
if (offset_day < 0) {
offset_day = offset_day + DAY_OF_WEEK;
} else if (offset_day == 0) {
offset_day = current_hour > default_start_hour ? DAY_OF_WEEK : offset_day;
}
int64_t offset_hour = default_start_hour - current_hour + offset_day * HOUR_OF_DAY;
start_usec = (total_hour_with_trunc + offset_hour) * USEC_OF_HOUR;
LOG_INFO("succeed to get window job info", K(start_usec), K(offset_hour), K(current_time),
K(total_hour_with_trunc), K(current_hour),
K(current_wday), K(nth_window), K(offset_sec),
K(default_start_hour), K(default_duration_usec),
K(job_action), K(offset_day));
}
}
return ret;
}
int ObDbmsStatsMaintenanceWindow::is_stats_maintenance_window_attr(const sql::ObSQLSessionInfo *session,
const ObString &job_name,
const ObString &attr_name,
const ObString &val_name,
bool &is_window_attr,
share::ObDMLSqlSplicer &dml)
{
int ret = OB_SUCCESS;
is_window_attr = false;
if (OB_ISNULL(session)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(session));
} else if (is_stats_job(job_name)) {
//now we just support modify job_action、start_date
if (0 == attr_name.case_compare("job_action")) {
if (0 == job_name.case_compare(opt_stats_history_manager)) {
const char *job_action_name = "DBMS_STATS.PURGE_STATS(";
if (0 == strncasecmp(val_name.ptr(), job_action_name, strlen(job_action_name))) {
if (OB_FAIL(dml.add_column("job_action", ObHexEscapeSqlStr(val_name)))) {
LOG_WARN("failed to add column", K(ret));
} else if (OB_FAIL(dml.add_column("what", ObHexEscapeSqlStr(val_name)))) {
LOG_WARN("failed to add column", K(ret));
} else {
is_window_attr = true;
}
} else {/*do nothing*/}
} else {
const char *job_action_name = "DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC(";
if (0 == strncasecmp(val_name.ptr(), job_action_name, strlen(job_action_name))) {
if (OB_FAIL(dml.add_column("job_action", ObHexEscapeSqlStr(val_name)))) {
LOG_WARN("failed to add column", K(ret));
} else if (OB_FAIL(dml.add_column("what", ObHexEscapeSqlStr(val_name)))) {
LOG_WARN("failed to add column", K(ret));
} else {
is_window_attr = true;
}
} else {/*do nothing*/}
}
} else if (0 == attr_name.case_compare("next_date")) {
ObObj time_obj;
ObObj src_obj;
int64_t current_time = ObTimeUtility::current_time();
ObArenaAllocator calc_buf("DbmsStatsWindow");
ObCastCtx cast_ctx(&calc_buf, NULL, CM_NONE, ObCharset::get_system_collation());
cast_ctx.dtc_params_ = session->get_dtc_params();
int64_t specify_time = -1;
int32_t offset_sec = 0;
src_obj.set_string(ObVarcharType, val_name);
const ObTimeZoneInfo* tz_info = get_timezone_info(session);
if (NULL != tz_info) {
if (OB_FAIL(tz_info->get_timezone_offset(ObTimeUtility::current_time(), offset_sec))) {
LOG_WARN("failed to get timezone offset", K(ret));
}
}
if (OB_FAIL(ret)) {
} else if (lib::is_oracle_mode()) {
if (OB_FAIL(ObObjCaster::to_type(ObTimestampTZType, cast_ctx, src_obj, time_obj))) {
LOG_WARN("failed to ObTimestampTZType type", K(ret));
} else {
specify_time = time_obj.get_otimestamp_value().time_us_;
}
} else if (lib::is_mysql_mode()) {
if (OB_FAIL(ObObjCaster::to_type(ObDateTimeType, cast_ctx, src_obj, time_obj))) {
LOG_WARN("failed to ObTimestampType type", K(ret));
} else {
specify_time = time_obj.get_datetime() - SEC_TO_USEC(offset_sec);
}
}
if (OB_SUCC(ret)) {
bool is_valid = false;
if (OB_FAIL(check_date_validate(job_name, specify_time + SEC_TO_USEC(offset_sec),
current_time + SEC_TO_USEC(offset_sec), is_valid))) {
LOG_WARN("failed to check date valid", K(ret));
} else if (!is_valid) {
ret = OB_ERR_DBMS_STATS_PL;
LOG_WARN("Invalid date", K(ret));
LOG_USER_ERROR(OB_ERR_DBMS_STATS_PL,
"The date is invalid. Please check wether they are the same day in a week, or the day is passed.");
} else if (OB_FAIL(dml.add_time_column("next_date", specify_time))) {
LOG_WARN("failed to add column", K(ret));
} else if (OB_FAIL(dml.add_time_column("start_date", specify_time))) {
LOG_WARN("failed to add column", K(ret));
} else {
is_window_attr = true;
LOG_TRACE("succeed to set next date", K(specify_time));
}
}
} else if (0 == attr_name.case_compare("duration")) {
// support set duration column.
int64_t specify_time = atol(val_name.ptr());
if (specify_time < 0 || specify_time > DEFAULT_DAY_INTERVAL_USEC) {
ret = OB_ERR_DBMS_STATS_PL;
LOG_WARN("the hour of interval must be between 0 and 24", K(ret));
LOG_USER_ERROR(OB_ERR_DBMS_STATS_PL, "the hour of interval must be between 0 and 24");
} else if (OB_FAIL(dml.add_column("max_run_duration", specify_time))) {
LOG_WARN("fail to add column", K(ret));
} else {
is_window_attr = true;
LOG_TRACE("succeed to set max_run_duration", K(val_name));
}
} else {/*do nothing*/
ret = OB_ERR_DBMS_STATS_PL;
ObSqlString errmsg;
errmsg.append_fmt("%.*s is not a valid window attribute.", attr_name.length(), attr_name.ptr());
LOG_USER_ERROR(OB_ERR_DBMS_STATS_PL, errmsg.ptr());
LOG_WARN("not a valid window attribute", K(errmsg));
}
}
return ret;
}
bool ObDbmsStatsMaintenanceWindow::is_stats_job(const ObString &job_name)
{
bool is_true = false;
for (int64_t i = 0; !is_true && i < DAY_OF_WEEK; ++i) {
if (0 == job_name.case_compare(windows_name[i])) {
is_true = true;
}
}
if (!is_true) {
is_true = (0 == job_name.case_compare(opt_stats_history_manager));
}
return is_true;
}
int ObDbmsStatsMaintenanceWindow::get_time_zone_offset(const ObSysVariableSchema &sys_variable,
const uint64_t tenant_id,
int32_t &offset_sec)
{
int ret = OB_SUCCESS;
bool is_oracle_mode = false;
const ObSysVarSchema *sysvar_schema = NULL;
if (OB_FAIL(sys_variable.get_oracle_mode(is_oracle_mode))) {
LOG_WARN("failed to get oracle mode", K(ret));
} else if (OB_FAIL(sys_variable.get_sysvar_schema(share::SYS_VAR_TIME_ZONE, sysvar_schema))) {
LOG_WARN("failed to get sysvar schema", K(ret));
} else if (OB_ISNULL(sysvar_schema)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(sysvar_schema));
} else {
ObArenaAllocator calc_buf(ObModIds::OB_SQL_PARSER);
char *buf = NULL;
int32_t buf_len = sysvar_schema->get_value().length();
if (OB_ISNULL(buf = static_cast<char*>(calc_buf.alloc(buf_len)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to allocate memory", K(ret), K(buf_len));
} else {
MEMCPY(buf, sysvar_schema->get_value().ptr(), buf_len);
ObString trimed_tz_str(buf_len, buf);
trimed_tz_str = trimed_tz_str.trim();
int ret_more = OB_SUCCESS;
if (OB_FAIL(ObTimeConverter::str_to_offset(trimed_tz_str, offset_sec, ret_more,
is_oracle_mode, true))) {
if (ret != OB_ERR_UNKNOWN_TIME_ZONE) {
LOG_WARN("fail to convert str_to_offset", K(trimed_tz_str), K(ret));
} else if (ret_more != OB_SUCCESS) {
ret = ret_more;
LOG_WARN("invalid time zone hour or minute", K(trimed_tz_str), K(ret));
}
}
if (OB_ERR_UNKNOWN_TIME_ZONE == ret) {
ObTimeZoneInfoPos tz_info;
ObTZMapWrap tz_map_wrap;
ObTimeZoneInfoManager *tz_info_mgr = NULL;
if (OB_FAIL(OTTZ_MGR.get_tenant_timezone(tenant_id, tz_map_wrap, tz_info_mgr))) {
LOG_WARN("get tenant timezone failed", K(ret));
} else if (OB_ISNULL(tz_info_mgr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("tz info mgr is null", K(ret));
} else if (OB_FAIL(tz_info_mgr->find_time_zone_info(trimed_tz_str, tz_info))) {
LOG_WARN("fail to find time zone", K(trimed_tz_str), K(ret));
} else if (OB_FAIL(tz_info.get_timezone_offset(ObTimeUtility::current_time(), offset_sec))) {
LOG_WARN("failed to get timezone offset", K(ret));
} else {/*do nothing*/}
}
}
}
return ret;
}
int ObDbmsStatsMaintenanceWindow::check_date_validate(const ObString &job_name,
const int64_t specify_time,
const int64_t current_time,
bool &is_valid)
{
int ret = OB_SUCCESS;
is_valid = false;
ObTime ob_time;
if (specify_time <= 0) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(specify_time));
} else if (current_time > specify_time) {
is_valid = false;
} else if (0 == job_name.case_compare(opt_stats_history_manager)) {
is_valid = true;
} else if (OB_FAIL(ObTimeConverter::usec_to_ob_time(specify_time, ob_time))) {
LOG_WARN("failed to usec to ob time", K(ret), K(specify_time));
} else if (OB_UNLIKELY(ob_time.parts_[DT_WDAY] < 1 ||
ob_time.parts_[DT_WDAY] > DAYS_PER_WEEK)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(ob_time.parts_[DT_WDAY]));
} else {
if (0 == job_name.case_compare(windows_name[ob_time.parts_[DT_WDAY]-1])) {
is_valid = true;
}
}
return ret;
}
int ObDbmsStatsMaintenanceWindow::reset_opt_stats_user_infos(ObIArray<const ObUserInfo *> &user_infos)
{
int ret = OB_SUCCESS;
if (user_infos.count() > 1) {
//bug:
//resver the minimum user id to execute
const ObUserInfo *minimum_user_info = user_infos.at(0);
for (int64_t i = 1; OB_SUCC(ret) && i < user_infos.count(); ++i) {
if (OB_ISNULL(minimum_user_info) || OB_ISNULL(user_infos.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(minimum_user_info), K(user_infos.at(i)));
} else if (minimum_user_info->get_user_id() > user_infos.at(i)->get_user_id()) {
minimum_user_info = user_infos.at(i);
} else {/*do nothing*/}
}
if (OB_SUCC(ret)) {
user_infos.reset();
if (OB_FAIL(user_infos.push_back(minimum_user_info))) {
LOG_WARN("failed to push back", K(ret));
}
}
}
return ret;
}
} // namespace common
} // namespace oceanbase