Forbid creating local unique index without covering all partition columns

This commit is contained in:
liboyang0730 2023-06-08 05:12:22 +00:00 committed by ob-robot
parent 5efdb4800d
commit 198891e5ba
4 changed files with 0 additions and 299 deletions

View File

@ -14096,18 +14096,6 @@ int ObDDLService::gen_hidden_index_schema_columns(const ObTableSchema &orig_inde
if (OB_FAIL(sql::ObResolverUtils::check_unique_index_cover_partition_column(
new_table_schema, create_index_arg))) {
LOG_WARN("fail to check unique key cover partition column", K(ret));
if (INDEX_TYPE_UNIQUE_LOCAL == create_index_arg.index_type_ &&
OB_EER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF == ret) {
int tmp_ret = OB_SUCCESS;
bool allow = false;
if (OB_SUCCESS != (tmp_ret = ObDDLResolver::check_uniq_allow(
new_table_schema, create_index_arg, allow))) {
LOG_WARN("fail to check uniq allow", K(ret));
} else if (allow) {
LOG_INFO("uniq index allowd, deduced by constraint", K(ret));
ret = OB_SUCCESS;
}
}
}
}
}

View File

@ -649,18 +649,6 @@ int ObIndexBuilder::generate_schema(
if (OB_FAIL(sql::ObResolverUtils::check_unique_index_cover_partition_column(
data_schema, arg))) {
RS_LOG(WARN, "fail to check unique key cover partition column", K(ret));
if (INDEX_TYPE_UNIQUE_LOCAL == arg.index_type_ &&
OB_EER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF == ret) {
int tmp_ret = OB_SUCCESS;
bool allow = false;
if (OB_SUCCESS != (tmp_ret = ObDDLResolver::check_uniq_allow(data_schema,
arg, allow))) {
RS_LOG(WARN, "fail to check uniq allow", K(ret));
} else if (allow) {
RS_LOG(INFO, "uniq index allowd, deduced by constraint", K(ret));
ret = OB_SUCCESS;
}
}
}
}
int64_t index_data_length = 0;

View File

@ -7123,271 +7123,6 @@ int ObDDLResolver::set_index_tablespace(const ObTableSchema &table_schema,
return ret;
}
int ObDDLResolver::check_uniq_allow(ObResolverParams &params,
ObTableSchema &table_schema,
const ObCreateIndexArg &index_arg,
ObRawExpr *part_func_expr,
ObIArray<ObRawExpr *> &constraint_exprs,
bool &allow)
{
int ret = OB_SUCCESS;
allow = false;
ObColumnRefRawExpr *part_col_expr = NULL;
if (!part_func_expr->is_column_ref_expr()) {
allow = false;
} else if (FALSE_IT(part_col_expr = static_cast<ObColumnRefRawExpr *>(part_func_expr))) {
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < index_arg.index_columns_.count() && !allow; ++i) {
const ObString &index_col_name = index_arg.index_columns_.at(i).column_name_;
const ObString &part_col_name = part_col_expr->get_column_name();
if (ObCharset::case_insensitive_equal(index_col_name, part_col_name)) {
allow = true;
} else {
// concern as base-column
for (int64_t j = 0; OB_SUCC(ret) && j < constraint_exprs.count() && !allow; ++j) {
ObOpRawExpr *check_expr = static_cast<ObOpRawExpr *>(constraint_exprs.at(j));
ObRawExpr *child_exprs[2] = {check_expr->get_param_expr(0), check_expr->get_param_expr(1)};
for (int64_t k = 0; OB_SUCC(ret) && k < 2 && !allow; ++k) {
if (child_exprs[k]->is_column_ref_expr()) {
ObColumnRefRawExpr *col_expr = static_cast<ObColumnRefRawExpr*>(child_exprs[k]);
if (ObCharset::case_insensitive_equal(part_col_name,
col_expr->get_column_name())) {
ObColumnRefRawExpr *cmp_col_expr = NULL;
if (!child_exprs[1 - k]->is_column_ref_expr()) {
cmp_col_expr = static_cast<ObColumnRefRawExpr*>(child_exprs[1 - k]->get_param_expr(0));
} else {
cmp_col_expr = static_cast<ObColumnRefRawExpr*>(child_exprs[1 - k]);
}
if (ObCharset::case_insensitive_equal(cmp_col_expr->get_column_name(), index_col_name)) {
allow = true;
}
}
}
}
}
// check gen column
if (OB_SUCC(ret) && !allow) {
ObColumnSchemaV2 *column_schema = NULL;
if (OB_ISNULL(column_schema = table_schema.get_column_schema(part_col_expr->get_column_id()))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Failed to get column schema", K(ret), K(part_col_expr->get_column_id()));
} else if (column_schema->is_generated_column()) {
ObString col_def;
ObRawExpr *gen_expr = NULL;
if (OB_FAIL(column_schema->get_orig_default_value().get_string(col_def))) {
LOG_WARN("get generated column definition failed", K(ret));
} else if (OB_FAIL(ObResolverUtils::resolve_generated_column_expr(params, col_def, table_schema,
*column_schema, gen_expr))) {
LOG_WARN("resolve generated column expr failed", K(ret));
} else {
ObString depend_part_col_name;
bool is_expect = true;
// check is substring or not
if (OB_ISNULL(gen_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("NULL ptr", K(ret));
} else if (T_FUN_SYS_SUBSTR != gen_expr->get_expr_type()) {
is_expect = false;
} else {
ObSysFunRawExpr *sys_expr = static_cast<ObSysFunRawExpr *>(gen_expr);
for (int64_t j = 0; OB_SUCC(ret) && j < sys_expr->get_param_count(); j++) {
ObRawExpr *param_expr = sys_expr->get_param_expr(j);
if (OB_ISNULL(param_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("NULL ptr", K(ret), K(param_expr));
} else if (0 == j && !param_expr->is_column_ref_expr()) {
is_expect = false;
} else if (0 != j && !param_expr->is_const_raw_expr()) {
is_expect = false;
}
}
if (OB_SUCC(ret) && is_expect) {
depend_part_col_name =
static_cast<ObColumnRefRawExpr *>(sys_expr->get_param_expr(0))->get_column_name();
}
if (OB_SUCC(ret) && !is_expect) {
continue;
}
}
for (int64_t j = 0; OB_SUCC(ret) && j < constraint_exprs.count() && !allow; ++j) {
ObOpRawExpr *check_expr = static_cast<ObOpRawExpr *>(constraint_exprs.at(j));
ObRawExpr *child_exprs[2] = {check_expr->get_param_expr(0), check_expr->get_param_expr(1)};
ObColumnRefRawExpr *col_exprs[2] = {NULL, NULL};
bool gen_expr_exist = false;
bool all_col = true;
for (int64_t k = 0; OB_SUCC(ret) && k < 2; ++k) {
if (child_exprs[k]->is_column_ref_expr()) {
col_exprs[k] = static_cast<ObColumnRefRawExpr*>(child_exprs[k]);
} else {
all_col = false;
col_exprs[k] = static_cast<ObColumnRefRawExpr*>(child_exprs[k]->get_param_expr(0));
if (!gen_expr_exist) {
ret = check_same_substr_expr(*child_exprs[k], *gen_expr, gen_expr_exist);
}
}
}
if (OB_SUCC(ret)) {
if (all_col || gen_expr_exist) {
if (ObCharset::case_insensitive_equal(col_exprs[0]->get_column_name(),
index_col_name) &&
ObCharset::case_insensitive_equal(col_exprs[1]->get_column_name(),
depend_part_col_name)) {
allow = true;
} else if (ObCharset::case_insensitive_equal(col_exprs[1]->get_column_name(),
index_col_name) &&
ObCharset::case_insensitive_equal(col_exprs[0]->get_column_name(),
depend_part_col_name)) {
allow = true;
}
}
}
}
}
}
}
}
}
}
return ret;
}
int ObDDLResolver::check_same_substr_expr(ObRawExpr &left, ObRawExpr &right, bool &same)
{
int ret = OB_SUCCESS;
same = true;
if (left.get_expr_type() != T_FUN_SYS_SUBSTR ||
right.get_expr_type() != T_FUN_SYS_SUBSTR) {
same = false;
} else {
ObSysFunRawExpr &sys_left = static_cast<ObSysFunRawExpr &>(left);
ObSysFunRawExpr &sys_right = static_cast<ObSysFunRawExpr &>(right);
if (sys_left.get_param_count() != sys_right.get_param_count()) {
same = false;
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < sys_left.get_param_count() && same; ++i) {
ObRawExpr *param_left = sys_left.get_param_expr(i);
ObRawExpr *param_right = sys_right.get_param_expr(i);
if (0 == i) {
if (!param_left->is_column_ref_expr() ||
!param_right->is_column_ref_expr()) {
same = false;
} else {
ObColumnRefRawExpr *col_left = static_cast<ObColumnRefRawExpr *>(param_left);
ObColumnRefRawExpr *col_right = static_cast<ObColumnRefRawExpr *>(param_right);
if (!ObCharset::case_insensitive_equal(col_left->get_column_name(),
col_right->get_column_name())) {
same = false;
}
}
} else {
if (!param_left->is_const_raw_expr() ||
!param_right->is_const_raw_expr()) {
same = false;
} else if (!param_left->same_as(*param_right)) {
same = false;
}
}
}
}
}
return ret;
}
int ObDDLResolver::check_uniq_allow(ObTableSchema &table_schema,
const ObCreateIndexArg &index_arg,
bool &allow)
{
int ret = OB_SUCCESS;
allow = false;
if (table_schema.get_part_level() == PARTITION_LEVEL_ONE &&
table_schema.get_part_option().is_list_part()) {
ObArenaAllocator allocator(ObModIds::OB_TEMP_VARIABLES);
ObResolverParams params;
ObRawExprFactory expr_factory(allocator);
SMART_VAR(sql::ObSQLSessionInfo, empty_session) {
uint64_t tenant_id = table_schema.get_tenant_id();
const ObTenantSchema *tenant_schema = NULL;
ObSchemaGetterGuard guard;
ObSchemaChecker schema_checker;
params.expr_factory_ = &expr_factory;
params.allocator_ = &allocator;
params.session_info_ = &empty_session;
if (OB_FAIL(empty_session.init(0, 0, &allocator))) {
LOG_WARN("init empty session failed", K(ret));
} else if (OB_FAIL(GCTX.schema_service_->get_tenant_schema_guard(tenant_id, guard))) {
LOG_WARN("get schema guard failed", K(ret));
} else if (OB_FAIL(guard.get_tenant_info(tenant_id, tenant_schema))) {
LOG_WARN("get tenant_schema failed", K(ret));
} else if (OB_FAIL(empty_session.init_tenant(tenant_schema->get_tenant_name_str(), tenant_id))) {
LOG_WARN("init tenant failed", K(ret));
} else if (OB_FAIL(empty_session.load_all_sys_vars(guard))) {
LOG_WARN("session load system variable failed", K(ret));
LOG_WARN("session load default system variable failed", K(ret));
} else if (OB_FAIL(empty_session.load_default_configs_in_pc())) {
LOG_WARN("session load default configs failed", K(ret));
} else if (OB_FAIL(schema_checker.init(guard))) {
LOG_WARN("failed to init schema checker", K(ret));
} else {
params.schema_checker_ = &schema_checker;
const share::schema::ObPartitionFuncType part_func_type = table_schema.get_part_option().get_part_func_type();
const ParseNode *node = NULL;
common::ObSEArray<common::ObString, 8> part_keys;
common::ObSEArray<ObRawExpr*, 8> part_func_exprs;
if (OB_FAIL(ObRawExprUtils::parse_expr_node_from_str(table_schema.get_part_option().get_part_func_expr_str(),
empty_session.get_local_collation_connection(),
*params.allocator_, node))) {
LOG_WARN("parse expr node from string failed", K(ret));
} else if (OB_FAIL(resolve_part_func(params,
node,
part_func_type,
table_schema,
part_func_exprs,
part_keys
))) {
SQL_RESV_LOG(WARN, "resolve part func failed", K(ret));
}
if (OB_SUCC(ret) && part_func_exprs.count() == 1) {
ObSEArray<ObRawExpr *, 8> check_exprs;
for (ObTableSchema::const_constraint_iterator iter = table_schema.constraint_begin(); OB_SUCC(ret) &&
iter != table_schema.constraint_end(); iter ++) {
ObConstraint cst;
ObRawExpr *check_expr = NULL;
if ((*iter)->get_constraint_type() != CONSTRAINT_TYPE_CHECK) {
continue;
} else if (OB_FAIL(ObRawExprUtils::parse_bool_expr_node_from_str((*iter)->get_check_expr_str(),
*params.allocator_, node))) {
LOG_WARN("parse expr node from string failed", K(ret));
} else if (OB_FAIL(resolve_check_constraint_expr(params, node, table_schema, cst, check_expr))) {
LOG_WARN("resolver constraint expr failed", K(ret));
} else {
ret = check_exprs.push_back(check_expr);
}
}
bool tmp_allow = false;
if (OB_FAIL(ret)) {
} else if (OB_FAIL(check_uniq_allow(params,
table_schema,
index_arg,
part_func_exprs.at(0),
check_exprs,
tmp_allow))) {
LOG_WARN("check_uniq_allowe failed", K(ret));
} else if (tmp_allow) {
allow = tmp_allow;
}
}
}
}
}
return ret;
}
int ObDDLResolver::resolve_split_partition_range_element(const ParseNode *node,
const share::schema::ObPartitionFuncType part_type,
const ObIArray<ObRawExpr *> &part_func_exprs,

View File

@ -167,9 +167,6 @@ public:
bool need_rewrite_length,
const bool is_byte_length = false);
static int rewrite_text_length_mysql(ObObjType &type, int32_t &length);
static int check_uniq_allow(share::schema::ObTableSchema &table_schema,
const obrpc::ObCreateIndexArg &index_arg,
bool &allow);
// check whether the column is allowed to be primary key.
int check_add_column_as_pk_allowed(const ObColumnSchemaV2 &column_schema);
static int get_primary_key_default_value(
@ -421,13 +418,6 @@ public:
bool is_oracle_mode,
bool is_explicit_order);
protected:
static int check_same_substr_expr(ObRawExpr &left, ObRawExpr &right, bool &same);
static int check_uniq_allow(ObResolverParams &params,
share::schema::ObTableSchema &table_schema,
const obrpc:: ObCreateIndexArg &index_arg,
ObRawExpr *part_func_expr,
common::ObIArray<ObRawExpr *> &constraint_exprs,
bool &allow);
static int get_part_str_with_type(
const bool is_oracle_mode,
share::schema::ObPartitionFuncType part_func_type,