408 lines
12 KiB
C++
408 lines
12 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.
|
|
*/
|
|
|
|
#ifndef OCEANBASE_SHARE_OB_DDL_COMMON_H
|
|
#define OCEANBASE_SHARE_OB_DDL_COMMON_H
|
|
|
|
#include "lib/allocator/page_arena.h"
|
|
#include "share/schema/ob_table_schema.h"
|
|
#include "share/schema/ob_schema_service.h"
|
|
#include "share/location_cache/ob_location_struct.h"
|
|
#include "storage/tablet/ob_tablet_common.h"
|
|
|
|
namespace oceanbase
|
|
{
|
|
namespace obrpc
|
|
{
|
|
class ObSrvRpcProxy;
|
|
class ObAlterTableArg;
|
|
}
|
|
namespace sql
|
|
{
|
|
class ObPhysicalPlan;
|
|
class ObOpSpec;
|
|
}
|
|
namespace storage
|
|
{
|
|
class ObTabletHandle;
|
|
class ObLSHandle;
|
|
}
|
|
namespace share
|
|
{
|
|
class ObLocationService;
|
|
enum ObDDLType
|
|
{
|
|
DDL_INVALID = 0,
|
|
|
|
///< @note add new normal long running ddl type before this line
|
|
DDL_CHECK_CONSTRAINT = 1,
|
|
DDL_FOREIGN_KEY_CONSTRAINT = 2,
|
|
DDL_ADD_NOT_NULL_COLUMN = 3,
|
|
DDL_MODIFY_AUTO_INCREMENT = 4,
|
|
DDL_CREATE_INDEX = 5,
|
|
DDL_DROP_INDEX = 6,
|
|
|
|
///< @note Drop schema, and refuse concurrent trans.
|
|
DDL_DROP_SCHEMA_AVOID_CONCURRENT_TRANS = 500,
|
|
DDL_DROP_DATABASE = 501,
|
|
DDL_DROP_TABLE = 502,
|
|
DDL_TRUNCATE_TABLE = 503,
|
|
DDL_DROP_PARTITION = 504,
|
|
DDL_DROP_SUB_PARTITION = 505,
|
|
DDL_TRUNCATE_PARTITION = 506,
|
|
DDL_TRUNCATE_SUB_PARTITION = 507,
|
|
|
|
///< @note add new double table long running ddl type before this line
|
|
DDL_DOUBLE_TABLE_OFFLINE = 1000,
|
|
DDL_MODIFY_COLUMN = 1001, // only modify columns
|
|
DDL_ADD_PRIMARY_KEY = 1002,
|
|
DDL_DROP_PRIMARY_KEY = 1003,
|
|
DDL_ALTER_PRIMARY_KEY = 1004,
|
|
DDL_ALTER_PARTITION_BY = 1005,
|
|
DDL_DROP_COLUMN = 1006, // only drop columns
|
|
DDL_CONVERT_TO_CHARACTER = 1007,
|
|
DDL_ADD_COLUMN_OFFLINE = 1008, // only add columns
|
|
DDL_COLUMN_REDEFINITION = 1009, // only add/drop columns
|
|
DDL_TABLE_REDEFINITION = 1010,
|
|
|
|
// @note new normal ddl type to be defined here !!!
|
|
DDL_NORMAL_TYPE = 10001,
|
|
DDL_ADD_COLUMN_ONLINE = 10002, // only add trailing columns
|
|
DDL_CHANGE_COLUMN_NAME = 10003,
|
|
///< @note add new normal ddl type before this line
|
|
DDL_MAX
|
|
};
|
|
|
|
enum ObDDLTaskType
|
|
{
|
|
INVALID_TASK = 0,
|
|
REBUILD_INDEX_TASK = 1,
|
|
REBUILD_CONSTRAINT_TASK = 2,
|
|
REBUILD_FOREIGN_KEY_TASK = 3,
|
|
MAKE_DDL_TAKE_EFFECT_TASK = 4,
|
|
CLEANUP_GARBAGE_TASK = 5,
|
|
MODIFY_FOREIGN_KEY_STATE_TASK = 6,
|
|
// used in rollback_failed_add_not_null_columns() in ob_constraint_task.cpp.
|
|
DELETE_COLUMN_FROM_SCHEMA = 7,
|
|
// remap all index tables to hidden table and take effect through one rpc, applied in drop column for 4.0.
|
|
REMAP_INDEXES_AND_TAKE_EFFECT_TASK = 8,
|
|
UPDATE_AUTOINC_SCHEMA = 9,
|
|
CANCEL_DDL_TASK = 10,
|
|
MODIFY_NOT_NULL_COLUMN_STATE_TASK = 11,
|
|
};
|
|
|
|
enum ObDDLTaskStatus {
|
|
PREPARE = 0,
|
|
LOCK_TABLE = 1,
|
|
WAIT_TRANS_END = 2,
|
|
REDEFINITION = 3,
|
|
VALIDATE_CHECKSUM = 4,
|
|
COPY_TABLE_DEPENDENT_OBJECTS = 5,
|
|
TAKE_EFFECT = 6,
|
|
CHECK_CONSTRAINT_VALID = 7,
|
|
SET_CONSTRAINT_VALIDATE = 8,
|
|
MODIFY_AUTOINC = 9,
|
|
SET_WRITE_ONLY = 10,
|
|
WAIT_TRANS_END_FOR_WRITE_ONLY = 11,
|
|
SET_UNUSABLE = 12,
|
|
WAIT_TRANS_END_FOR_UNUSABLE = 13,
|
|
DROP_SCHEMA = 14,
|
|
CHECK_TABLE_EMPTY = 15,
|
|
WAIT_CHILD_TASK_FINISH = 16,
|
|
FAIL = 99,
|
|
SUCCESS = 100
|
|
};
|
|
|
|
static inline bool is_simple_table_long_running_ddl(const ObDDLType type)
|
|
{
|
|
return type > DDL_INVALID && type < DDL_DROP_SCHEMA_AVOID_CONCURRENT_TRANS;
|
|
}
|
|
|
|
static inline bool is_drop_schema_block_concurrent_trans(const ObDDLType type)
|
|
{
|
|
return type > DDL_DROP_SCHEMA_AVOID_CONCURRENT_TRANS && type < DDL_DOUBLE_TABLE_OFFLINE;
|
|
}
|
|
|
|
static inline bool is_double_table_long_running_ddl(const ObDDLType type)
|
|
{
|
|
return type > DDL_DOUBLE_TABLE_OFFLINE && type < DDL_NORMAL_TYPE;
|
|
}
|
|
|
|
static inline bool is_long_running_ddl(const ObDDLType type)
|
|
{
|
|
return is_simple_table_long_running_ddl(type) || is_double_table_long_running_ddl(type);
|
|
}
|
|
|
|
static inline bool is_invalid_ddl_type(const ObDDLType type)
|
|
{
|
|
return DDL_INVALID == type;
|
|
}
|
|
|
|
struct ObColumnNameInfo final
|
|
{
|
|
public:
|
|
ObColumnNameInfo()
|
|
: column_name_(), is_shadow_column_(false)
|
|
{}
|
|
ObColumnNameInfo(const ObString &column_name, const bool is_shadow_column)
|
|
: column_name_(column_name), is_shadow_column_(is_shadow_column)
|
|
{}
|
|
~ObColumnNameInfo() = default;
|
|
TO_STRING_KV(K_(column_name), K_(is_shadow_column));
|
|
public:
|
|
ObString column_name_;
|
|
bool is_shadow_column_;
|
|
};
|
|
|
|
class ObColumnNameMap final {
|
|
public:
|
|
ObColumnNameMap() {}
|
|
~ObColumnNameMap() {}
|
|
int init(const schema::ObTableSchema &orig_table_schema,
|
|
const schema::AlterTableSchema &alter_table_arg);
|
|
int assign(const ObColumnNameMap &other);
|
|
int set(const ObString &orig_column_name, const ObString &new_column_name);
|
|
int get(const ObString &orig_column_name, ObString &new_column_name) const;
|
|
int get_orig_column_name(const ObString &new_column_name, ObString &orig_column_name) const;
|
|
int get_changed_names(ObIArray<std::pair<ObString, ObString>> &changed_names) const;
|
|
DECLARE_TO_STRING;
|
|
|
|
private:
|
|
ObArenaAllocator allocator_;
|
|
lib::Worker::CompatMode compat_mode_;
|
|
common::hash::ObHashMap<schema::ObColumnNameHashWrapper, ObString> col_name_map_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(ObColumnNameMap);
|
|
};
|
|
|
|
class ObDDLUtil
|
|
{
|
|
public:
|
|
struct ObReplicaKey final
|
|
{
|
|
public:
|
|
ObReplicaKey(): partition_id_(common::OB_INVALID_ID), addr_()
|
|
{}
|
|
ObReplicaKey(const int64_t partition_id, common::ObAddr addr): partition_id_(partition_id), addr_(addr)
|
|
{}
|
|
~ObReplicaKey() = default;
|
|
uint64_t hash() const
|
|
{
|
|
uint64_t hash_val = addr_.hash();
|
|
hash_val = murmurhash(&partition_id_, sizeof(partition_id_), hash_val);
|
|
return hash_val;
|
|
}
|
|
bool operator ==(const ObReplicaKey &other) const
|
|
{
|
|
return partition_id_ == other.partition_id_ && addr_ == other.addr_;
|
|
}
|
|
|
|
TO_STRING_KV(K_(partition_id), K_(addr));
|
|
public:
|
|
int64_t partition_id_;
|
|
common::ObAddr addr_;
|
|
};
|
|
|
|
// get all tablets of a table by table_id
|
|
static int get_tablets(
|
|
const uint64_t tenant_id,
|
|
const int64_t table_id,
|
|
common::ObIArray<common::ObTabletID> &tablet_ids);
|
|
|
|
// get all tablets of a table by table_schema
|
|
static int get_tablets(
|
|
const share::schema::ObTableSchema &table_schema,
|
|
common::ObIArray<common::ObTabletID> &tablet_ids);
|
|
|
|
// check if the major sstable of a table are exist in all needed replicas
|
|
static int check_major_sstable_complete(
|
|
const uint64_t data_table_id,
|
|
const uint64_t index_table_id,
|
|
const int64_t snapshot_version,
|
|
bool &is_complete);
|
|
|
|
static int generate_build_replica_sql(
|
|
const uint64_t tenant_id,
|
|
const int64_t data_table_id,
|
|
const int64_t dest_table_id,
|
|
const int64_t schema_version,
|
|
const int64_t snapshot_version,
|
|
const int64_t execution_id,
|
|
const int64_t task_id,
|
|
const int64_t parallelism,
|
|
const bool use_heap_table_ddl_plan,
|
|
const bool use_schema_version_hint_for_src_table,
|
|
const ObColumnNameMap *col_name_map,
|
|
ObSqlString &sql_string);
|
|
|
|
static int get_tablet_leader_addr(
|
|
share::ObLocationService *location_service,
|
|
const uint64_t tenant_id,
|
|
const common::ObTabletID &tablet_id,
|
|
const int64_t timeout,
|
|
share::ObLSID &ls_id,
|
|
common::ObAddr &leader_addr);
|
|
|
|
static int refresh_alter_table_arg(
|
|
const uint64_t tenant_id,
|
|
const int64_t orig_table_id,
|
|
obrpc::ObAlterTableArg &alter_table_arg);
|
|
|
|
static int generate_ddl_schema_hint_str(
|
|
const ObString &table_name,
|
|
const int64_t schema_version,
|
|
const bool is_oracle_mode,
|
|
ObSqlString &sql_string);
|
|
|
|
static int ddl_get_tablet(
|
|
storage::ObLSHandle &ls_handle,
|
|
const ObTabletID &tablet_id,
|
|
storage::ObTabletHandle &tablet_handle,
|
|
const int64_t timeout_us = storage::ObTabletCommon::DEFAULT_GET_TABLET_TIMEOUT_US);
|
|
|
|
static int clear_ddl_checksum(sql::ObPhysicalPlan *phy_plan);
|
|
|
|
static bool is_table_lock_retry_ret_code(int ret)
|
|
{
|
|
return OB_TRY_LOCK_ROW_CONFLICT == ret || OB_NOT_MASTER == ret || OB_TIMEOUT == ret
|
|
|| OB_EAGAIN == ret || OB_LS_LOCATION_LEADER_NOT_EXIST == ret;
|
|
}
|
|
static bool need_remote_write(const int ret_code);
|
|
|
|
static int check_can_convert_character(const ObObjMeta &obj_meta)
|
|
{
|
|
return (obj_meta.is_string_type() || obj_meta.is_enum_or_set())
|
|
&& CS_TYPE_BINARY != obj_meta.get_collation_type();
|
|
}
|
|
|
|
static int get_sys_ls_leader_addr(
|
|
const uint64_t cluster_id,
|
|
const uint64_t tenant_id,
|
|
common::ObAddr &leader_addr);
|
|
|
|
static int get_tablet_paxos_member_list(
|
|
const uint64_t tenant_id,
|
|
const common::ObTabletID &tablet_id,
|
|
common::ObIArray<common::ObAddr> &paxos_server_list,
|
|
int64_t &paxos_member_count);
|
|
|
|
static int get_tablet_replica_location(
|
|
const uint64_t tenant_id,
|
|
const common::ObTabletID &tablet_id,
|
|
ObLSLocation &location);
|
|
|
|
static int check_table_exist(
|
|
const uint64_t tenant_id,
|
|
const uint64_t table_id,
|
|
share::schema::ObSchemaGetterGuard &schema_guard);
|
|
|
|
private:
|
|
static int generate_column_name_str(
|
|
const common::ObIArray<ObColumnNameInfo> &column_names,
|
|
const bool is_oracle_mode,
|
|
const bool with_origin_name,
|
|
const bool with_alias_name,
|
|
const bool use_heap_table_ddl_plan,
|
|
ObSqlString &column_name_str);
|
|
static int generate_column_name_str(
|
|
const ObColumnNameInfo &column_name_info,
|
|
const bool is_oracle_mode,
|
|
const bool with_origin_name,
|
|
const bool with_alias_name,
|
|
const bool with_comma,
|
|
ObSqlString &sql_string);
|
|
static int generate_order_by_str(
|
|
const ObIArray<int64_t> &select_column_ids,
|
|
const ObIArray<int64_t> &order_column_ids,
|
|
ObSqlString &sql_string);
|
|
static int find_table_scan_table_id(
|
|
const sql::ObOpSpec *spec,
|
|
uint64_t &table_id);
|
|
};
|
|
|
|
|
|
class ObCheckTabletDataComplementOp
|
|
{
|
|
public:
|
|
|
|
static int check_and_wait_old_complement_task(
|
|
const uint64_t tenant_id,
|
|
const uint64_t index_table_id,
|
|
const common::ObAddr &inner_sql_exec_addr,
|
|
const common::ObCurTraceId::TraceId &trace_id,
|
|
const int64_t schema_version,
|
|
const int64_t scn,
|
|
bool &need_exec_new_inner_sql);
|
|
|
|
private:
|
|
|
|
static int check_all_tablet_sstable_status(
|
|
const uint64_t tenant_id,
|
|
const uint64_t index_table_id,
|
|
const int64_t snapshot_version,
|
|
bool &is_all_sstable_build_finished);
|
|
|
|
static int check_task_inner_sql_session_status(
|
|
const common::ObAddr &inner_sql_exec_addr,
|
|
const common::ObCurTraceId::TraceId &trace_id,
|
|
const uint64_t tenant_id,
|
|
const int64_t schema_version,
|
|
const int64_t scn,
|
|
bool &is_old_task_session_exist);
|
|
|
|
static int do_check_tablets_merge_status(
|
|
const uint64_t tenant_id,
|
|
const int64_t snapshot_version,
|
|
const ObIArray<ObTabletID> &tablet_ids,
|
|
const ObLSID &ls_id,
|
|
hash::ObHashMap<ObAddr, ObArray<ObTabletID>> &ip_tablets_map,
|
|
hash::ObHashMap<ObTabletID, int32_t> &tablets_commited_map,
|
|
int64_t &tablet_commit_count);
|
|
|
|
static int check_tablet_merge_status(
|
|
const uint64_t tenant_id,
|
|
const ObIArray<common::ObTabletID> &tablet_ids,
|
|
const int64_t snapshot_version,
|
|
bool &is_all_tablets_commited);
|
|
|
|
static int update_replica_merge_status(
|
|
const ObTabletID &tablet_id,
|
|
const int merge_status,
|
|
hash::ObHashMap<ObTabletID, int32_t> &tablets_commited_map);
|
|
|
|
|
|
static int calculate_build_finish(
|
|
const uint64_t tenant_id,
|
|
const common::ObIArray<common::ObTabletID> &tablet_ids,
|
|
hash::ObHashMap<ObTabletID, int32_t> &tablets_commited_map,
|
|
int64_t &commit_succ_count);
|
|
|
|
static int construct_ls_tablet_map(
|
|
const uint64_t tenant_id,
|
|
const common::ObTabletID &tablet_id,
|
|
hash::ObHashMap<ObLSID, ObArray<ObTabletID>> &ls_tablets_map);
|
|
|
|
static int construct_tablet_ip_map(
|
|
const uint64_t tenant_id,
|
|
const ObTabletID &tablet_id,
|
|
hash::ObHashMap<ObAddr, ObArray<ObTabletID>> &ip_tablets_map);
|
|
|
|
};
|
|
|
|
|
|
|
|
} // end namespace share
|
|
} // end namespace oceanbase
|
|
|
|
#endif // OCEANBASE_SHARE_OB_DDL_COMMON_H
|
|
|