fix mv rewrite with partition hint bug

This commit is contained in:
hy-guo 2024-11-06 11:13:50 +00:00 committed by ob-robot
parent 9d11d972f9
commit 2e5a3cf0d0
5 changed files with 36 additions and 32 deletions

View File

@ -1384,18 +1384,15 @@ int ObStmtComparer::compute_tables_map(const ObDMLStmt *first,
}
int ObStmtComparer::compare_basic_table_item(const ObDMLStmt *first,
const TableItem *first_table,
const ObDMLStmt *second,
const TableItem *second_table,
QueryRelation &relation)
int ObStmtComparer::compare_basic_table_item(const TableItem *first_table,
const TableItem *second_table,
QueryRelation &relation)
{
int ret = OB_SUCCESS;
relation = QueryRelation::QUERY_UNCOMPARABLE;
if (OB_ISNULL(first) || OB_ISNULL(first_table)
|| OB_ISNULL(second) || OB_ISNULL(second_table)) {
if (OB_ISNULL(first_table) || OB_ISNULL(second_table)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("param has null", K(first), K(first_table), K(second), K(second_table));
LOG_WARN("param has null", K(first_table), K(second_table));
} else if ((first_table->is_basic_table() || first_table->is_link_table())
&& (second_table->is_basic_table() || second_table->is_link_table())
&& first_table->ref_id_ == second_table->ref_id_
@ -1568,11 +1565,9 @@ int ObStmtComparer::compare_table_item(const ObDMLStmt *first,
}
} else if ((first_table->is_basic_table() || first_table->is_link_table()) &&
(second_table->is_basic_table() || second_table->is_link_table())) {
if (OB_FAIL(compare_basic_table_item(first,
first_table,
second,
second_table,
relation))) {
if (OB_FAIL(compare_basic_table_item(first_table,
second_table,
relation))) {
LOG_WARN("compare table part failed",K(ret), K(first_table), K(second_table));
} else if (QueryRelation::QUERY_UNCOMPARABLE != relation) {
const int32_t first_table_index = first->get_table_bit_index(first_table->table_id_);

View File

@ -338,11 +338,9 @@ public:
* partition hint
* generated_table只比较引用的子查询是否相同
*/
static int compare_basic_table_item (const ObDMLStmt *first,
const TableItem *first_table,
const ObDMLStmt *second,
const TableItem *second_table,
QueryRelation &relation);
static int compare_basic_table_item (const TableItem *first_table,
const TableItem *second_table,
QueryRelation &relation);
/**
* @brief compare_joined_table_item

View File

@ -257,7 +257,7 @@ int ObTransformMVRewrite::gen_base_table_map(const ObIArray<TableItem*> &from_ta
if (OB_ISNULL(from_table)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null table", K(ret), K(i));
} else if (!(from_table->is_basic_table() || from_table->is_generated_table())
} else if (!(from_table->is_basic_table() || from_table->is_link_table())
|| OB_INVALID_ID == from_table->ref_id_) {
// do nothing
} else if (NULL == (num = from_table_num.get(from_table->ref_id_))) {
@ -275,7 +275,7 @@ int ObTransformMVRewrite::gen_base_table_map(const ObIArray<TableItem*> &from_ta
if (OB_ISNULL(to_table)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null table", K(ret), K(i));
} else if (!(to_table->is_basic_table() || to_table->is_generated_table())
} else if (!(to_table->is_basic_table() || to_table->is_link_table())
|| OB_INVALID_ID == to_table->ref_id_) {
// do nothing
} else if (NULL == (idx = to_table_map.get(to_table->ref_id_))) {
@ -301,6 +301,7 @@ int ObTransformMVRewrite::gen_base_table_map(const ObIArray<TableItem*> &from_ta
LOG_WARN("failed to prepare allocate map array", K(ret), K(from_tables.count()));
} else if (OB_FAIL(inner_gen_base_table_map(0,
from_tables,
to_tables,
from_table_num,
to_table_ids,
to_table_map,
@ -321,6 +322,7 @@ int ObTransformMVRewrite::gen_base_table_map(const ObIArray<TableItem*> &from_ta
// generate a base table map for from_table_idx-th from table
int ObTransformMVRewrite::inner_gen_base_table_map(int64_t from_table_idx,
const ObIArray<TableItem*> &from_tables,
const ObIArray<TableItem*> &to_tables,
hash::ObHashMap<uint64_t, int64_t> &from_table_num,
const ObIArray<ObSEArray<int64_t,4>> &to_table_ids,
const hash::ObHashMap<uint64_t, int64_t> &to_table_map,
@ -352,13 +354,14 @@ int ObTransformMVRewrite::inner_gen_base_table_map(int64_t from_table_idx,
if (OB_ISNULL(from_table)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("from table item is NULL", K(ret), K(from_table_idx));
} else if (!(from_table->is_basic_table() || from_table->is_generated_table())
} else if (!(from_table->is_basic_table() || from_table->is_link_table())
|| OB_INVALID_ID == from_table->ref_id_
|| NULL == (to_idx = to_table_map.get(from_table->ref_id_))) {
// table does not exists in to_tables
// table does not exists in to_tables, map from_table to nothing
current_map.at(from_table_idx) = -1;
if (OB_FAIL(SMART_CALL(inner_gen_base_table_map(from_table_idx + 1,
from_tables,
to_tables,
from_table_num,
to_table_ids,
to_table_map,
@ -372,17 +375,27 @@ int ObTransformMVRewrite::inner_gen_base_table_map(int64_t from_table_idx,
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected to_idx", K(ret), K(*to_idx));
} else {
bool has_mapped = false;
// try to map from_table to to_table which has same ref_id and not be used
for (int64_t i = 0; OB_SUCC(ret) && max_map_num > table_maps.count()
&& i < to_table_ids.at(*to_idx).count(); ++i) {
int64_t to_table_idx = to_table_ids.at(*to_idx).at(i);
QueryRelation relation = QueryRelation::QUERY_UNCOMPARABLE;
if (used_to_table.has_member(to_table_idx)) {
// do nothing, to_table has been used
} else if (OB_FAIL(ObStmtComparer::compare_basic_table_item(from_tables.at(from_table_idx),
to_tables.at(to_table_idx),
relation))) {
LOG_WARN("failed to compare basic table", K(ret), K(from_table_idx), K(to_table_idx));
} else if (QueryRelation::QUERY_EQUAL != relation) {
// do nothing, from table and to table are not equal
} else if (OB_FALSE_IT(has_mapped = true)) {
} else if (OB_FAIL(used_to_table.add_member(to_table_idx))) {
LOG_WARN("failed to add member", K(ret));
} else if (OB_FALSE_IT(current_map.at(from_table_idx) = to_table_idx)) {
} else if (OB_FAIL(SMART_CALL(inner_gen_base_table_map(from_table_idx + 1,
from_tables,
to_tables,
from_table_num,
to_table_ids,
to_table_map,
@ -397,20 +410,19 @@ int ObTransformMVRewrite::inner_gen_base_table_map(int64_t from_table_idx,
}
// try to map from_table to nothing
int64_t from_num; // number of from tables with the same ref_id minus table has been mapped to -1
if (OB_FAIL(ret) || max_map_num <= table_maps.count()
|| !(from_table->is_basic_table() || from_table->is_generated_table())
|| OB_INVALID_ID == from_table->ref_id_) {
if (OB_FAIL(ret) || max_map_num <= table_maps.count()) {
// do nothing
} else if (OB_FAIL(from_table_num.get_refactored(from_table->ref_id_, from_num))) {
LOG_WARN("failed to get from table num", K(ret), KPC(from_table));
} else if (from_num <= to_table_ids.at(*to_idx).count()) {
} else if (has_mapped && from_num <= to_table_ids.at(*to_idx).count()) {
// do nothing, the number of remaining unmapped from tables is less than or equal to
// the number of remaining to tables, can not map from_table to nothing.
// the number of remaining to tables, should not map from_table to nothing.
} else if (OB_FAIL(from_table_num.set_refactored(from_table->ref_id_, from_num - 1, 1))) {
LOG_WARN("failed to set from table num", K(ret), KPC(from_table));
} else if (OB_FALSE_IT(current_map.at(from_table_idx) = -1)) {
} else if (OB_FAIL(SMART_CALL(inner_gen_base_table_map(from_table_idx + 1,
from_tables,
to_tables,
from_table_num,
to_table_ids,
to_table_map,

View File

@ -200,6 +200,7 @@ private:
ObIArray<ObSEArray<int64_t,4>> &table_maps);
int inner_gen_base_table_map(int64_t from_rel_id,
const ObIArray<TableItem*> &from_tables,
const ObIArray<TableItem*> &to_tables,
hash::ObHashMap<uint64_t, int64_t> &from_table_num,
const ObIArray<ObSEArray<int64_t,4>> &to_table_ids,
const hash::ObHashMap<uint64_t, int64_t> &to_table_map,

View File

@ -6272,11 +6272,9 @@ int ObTransformUtils::check_table_item_containment(ObDMLStmt *source_stmt,
} else if (source_table->is_basic_table() && target_table->is_basic_table()) {
QueryRelation relation = QueryRelation::QUERY_UNCOMPARABLE;
//zhenling.zzg 修复存在partition hint的情况下,正确性bug
if (OB_FAIL(ObStmtComparer::compare_basic_table_item(source_stmt,
source_table,
target_stmt,
target_table,
relation))) {
if (OB_FAIL(ObStmtComparer::compare_basic_table_item(source_table,
target_table,
relation))) {
LOG_WARN("compare table part failed",K(ret), K(source_table), K(target_table));
} else if (QueryRelation::QUERY_LEFT_SUBSET == relation ||
QueryRelation::QUERY_EQUAL == relation) {