disable join elimination for delete/update when the eliminated table is also a deleted/updated table
This commit is contained in:
		@ -60,7 +60,29 @@ int ObTransformJoinElimination::transform_one_stmt(
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObTransformJoinElimination::eliminate_join_self_foreign_key(ObDMLStmt* stmt, bool& trans_happened)
 | 
			
		||||
int ObTransformJoinElimination::check_table_can_be_eliminated(const ObDMLStmt *stmt, uint64_t table_id, bool &is_valid)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  is_valid = true;
 | 
			
		||||
  if (OB_ISNULL(stmt)) {
 | 
			
		||||
    ret = OB_ERR_UNEXPECTED;
 | 
			
		||||
    LOG_WARN("get unexpected null stmt", K(ret));
 | 
			
		||||
  } else if (stmt->is_delete_stmt() || stmt->is_update_stmt()) {
 | 
			
		||||
    const ObDelUpdStmt *del_up_stmt = static_cast<const ObDelUpdStmt *>(stmt);
 | 
			
		||||
    for (uint64_t i = 0; OB_SUCC(ret) && i < del_up_stmt->get_all_table_columns().count(); ++i) {
 | 
			
		||||
      const TableColumns &tab_cols = del_up_stmt->get_all_table_columns().at(i);
 | 
			
		||||
      const IndexDMLInfo &index_info = tab_cols.index_dml_infos_.at(0);
 | 
			
		||||
      if (index_info.table_id_ == table_id) {
 | 
			
		||||
        is_valid = false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    // TODO: add more cases if necessary
 | 
			
		||||
  }
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ObTransformJoinElimination::eliminate_join_self_foreign_key(ObDMLStmt *stmt, bool &trans_happened)
 | 
			
		||||
{
 | 
			
		||||
  int ret = OB_SUCCESS;
 | 
			
		||||
  bool from_happedend = false;
 | 
			
		||||
@ -1707,6 +1729,7 @@ int ObTransformJoinElimination::eliminate_candi_tables(ObDMLStmt* stmt, ObIArray
 | 
			
		||||
  trans_happened = false;
 | 
			
		||||
  EqualSets* equal_sets = &ctx_->equal_sets_;
 | 
			
		||||
  ObArenaAllocator allocator;
 | 
			
		||||
  bool is_valid = true;
 | 
			
		||||
  if (conds.empty()) {
 | 
			
		||||
    /*do nothing*/
 | 
			
		||||
  } else if (OB_FAIL(ObEqualAnalysis::compute_equal_set(&allocator, conds, *equal_sets))) {
 | 
			
		||||
@ -1721,6 +1744,10 @@ int ObTransformJoinElimination::eliminate_candi_tables(ObDMLStmt* stmt, ObIArray
 | 
			
		||||
        for (int64_t j = 0; OB_SUCC(ret) && j < candi_tables.count(); ++j) {
 | 
			
		||||
          if (i == j || removed_items.has_member(j)) {
 | 
			
		||||
            /*do nothing*/
 | 
			
		||||
          } else if (OB_FAIL(check_table_can_be_eliminated(stmt, candi_tables.at(j)->table_id_, is_valid))) {
 | 
			
		||||
            LOG_WARN("check table can be eliminated failed", K(ret));
 | 
			
		||||
          } else if (!is_valid) {
 | 
			
		||||
            // do nothing
 | 
			
		||||
          } else if (OB_FAIL(do_join_elimination_self_key(
 | 
			
		||||
                         stmt, candi_tables.at(i), candi_tables.at(j), is_happened, equal_sets))) {
 | 
			
		||||
            LOG_WARN("failed to eliminate self key join in base table", K(ret));
 | 
			
		||||
@ -1734,8 +1761,13 @@ int ObTransformJoinElimination::eliminate_candi_tables(ObDMLStmt* stmt, ObIArray
 | 
			
		||||
        }
 | 
			
		||||
        is_happened = false;
 | 
			
		||||
        for (int64_t j = 0; OB_SUCC(ret) && !is_happened && j < child_candi_tables.count(); ++j) {
 | 
			
		||||
          if (OB_FAIL(do_join_elimination_self_key(
 | 
			
		||||
                  stmt, child_candi_tables.at(j), candi_tables.at(i), is_happened, equal_sets))) {
 | 
			
		||||
          is_valid = true;
 | 
			
		||||
          if (OB_FAIL(check_table_can_be_eliminated(stmt, candi_tables.at(i)->table_id_, is_valid))) {
 | 
			
		||||
            LOG_WARN("check table can be eliminated failed", K(ret));
 | 
			
		||||
          } else if (!is_valid) {
 | 
			
		||||
            // do nothing
 | 
			
		||||
          } else if (OB_FAIL(do_join_elimination_self_key(
 | 
			
		||||
                         stmt, child_candi_tables.at(j), candi_tables.at(i), is_happened, equal_sets))) {
 | 
			
		||||
            LOG_WARN("failed to do join elimination erlf key", K(ret));
 | 
			
		||||
          } else if (!is_happened) {
 | 
			
		||||
            /*do nothing*/
 | 
			
		||||
 | 
			
		||||
@ -55,9 +55,32 @@ public:
 | 
			
		||||
      common::ObIArray<ObParentDMLStmt>& parent_stmts, ObDMLStmt*& stmt, bool& trans_happened) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  int eliminate_join_self_foreign_key(ObDMLStmt* stmt, bool& trans_happened);
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief
 | 
			
		||||
   * check if a table can be eliminated
 | 
			
		||||
   *  delete p1, p2 FROM t1  as p1, t1 as p2 where p1.a=p2.a;
 | 
			
		||||
   * p2 can not be eliminateed since it is going to be updated/deleted
 | 
			
		||||
   * @param stmt
 | 
			
		||||
   * @param table_id
 | 
			
		||||
   * @param is_valid
 | 
			
		||||
   * @return int
 | 
			
		||||
   */
 | 
			
		||||
  int check_table_can_be_eliminated(const ObDMLStmt *stmt, uint64_t table_id, bool &is_valid);
 | 
			
		||||
 | 
			
		||||
  int eliminate_join_in_from_base_table(ObDMLStmt* stmt, bool& trans_happened);
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief eliminate_join_self_key
 | 
			
		||||
   * cases that can be eliminated for self key join:
 | 
			
		||||
   * basic_table or generate_table within STMT FROM ITEMS
 | 
			
		||||
   * basic_table or generate_table within SEMI ITEMS
 | 
			
		||||
   * inner join tables within SEMI ITEMS or STMT ITEMS
 | 
			
		||||
   */
 | 
			
		||||
  int eliminate_join_self_foreign_key(ObDMLStmt *stmt, bool &trans_happened);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * @brief eliminate_SKJ_in_from_base_table
 | 
			
		||||
   * eliminate self key loseless join existed in basic table or generate table within STMT FROM ITEMS
 | 
			
		||||
   */
 | 
			
		||||
  int eliminate_join_in_from_base_table(ObDMLStmt *stmt, bool &trans_happened);
 | 
			
		||||
 | 
			
		||||
  int eliminate_join_in_from_item(
 | 
			
		||||
      ObDMLStmt* stmt, const ObIArray<FromItem>& from_items, SemiInfo* semi_info, bool& trans_happened);
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user