fix query pushdown into set stmt bug
This commit is contained in:
		| @ -3245,6 +3245,21 @@ int ObRawExprUtils::extract_set_op_exprs(const ObRawExpr *raw_expr, | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| int ObRawExprUtils::extract_set_op_exprs(const ObIArray<ObRawExpr*> &exprs, | ||||
|                                          common::ObIArray<ObRawExpr*> &set_op_exprs) | ||||
| { | ||||
|   int ret = OB_SUCCESS; | ||||
|   for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) { | ||||
|     if (OB_ISNULL(exprs.at(i))) { | ||||
|       ret = OB_INVALID_ARGUMENT; | ||||
|       LOG_WARN("Expr is NULL", K(ret), K(i)); | ||||
|     } else if (OB_FAIL(extract_set_op_exprs(exprs.at(i), set_op_exprs))) { | ||||
|       LOG_WARN("Failed to extract column exprs", K(ret)); | ||||
|     } | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| int ObRawExprUtils::extract_column_exprs(const ObRawExpr *raw_expr, | ||||
|                                          ObIArray<ObRawExpr*> &column_exprs, | ||||
|                                          bool need_pseudo_column) | ||||
|  | ||||
| @ -372,6 +372,8 @@ public: | ||||
|   static bool is_all_column_exprs(const common::ObIArray<ObRawExpr*> &exprs); | ||||
|   static int extract_set_op_exprs(const ObRawExpr *raw_expr, | ||||
|                                   common::ObIArray<ObRawExpr*> &set_op_exprs); | ||||
|   static int extract_set_op_exprs(const ObIArray<ObRawExpr*> &exprs, | ||||
|                                   common::ObIArray<ObRawExpr*> &set_op_exprs); | ||||
|   /// extract column exprs from the raw expr | ||||
|   static int extract_column_exprs(const ObRawExpr *raw_expr, | ||||
|                                   common::ObIArray<ObRawExpr*> &column_exprs, | ||||
|  | ||||
| @ -414,6 +414,12 @@ int ObTransformQueryPushDown::is_select_item_same(ObSelectStmt *select_stmt, | ||||
|       if (column_count == view_stmt->get_select_item_size()) { | ||||
|         /*do nothing*/ | ||||
|       //if outer output is const expr, then inner output must be const expr, eg:select 1 from (select 2 from t1) | ||||
|       } else if (OB_FAIL(check_set_op_expr_reference(select_stmt, view_stmt, | ||||
|                                                      select_offset, is_same))) { | ||||
|         LOG_WARN("failed to check select item reference", K(ret)); | ||||
|       } else if (!is_same) { | ||||
|         // view stmt is set stmt and outer output not contain all set op exprs in relation exprs of view | ||||
|         // eg: select 1, c1 from (select 2 c1, 3 c2 from t1 union all select 4, 5 from t2 order by union[2]) v | ||||
|       } else if (const_select_items.count() == select_stmt->get_select_item_size()) { | ||||
|         for (int64_t i = 0; OB_SUCC(ret) && is_same && i < view_stmt->get_select_item_size(); ++i) { | ||||
|           ObRawExpr *select_expr = NULL; | ||||
| @ -440,6 +446,49 @@ int ObTransformQueryPushDown::is_select_item_same(ObSelectStmt *select_stmt, | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| int ObTransformQueryPushDown::check_set_op_expr_reference(ObSelectStmt *select_stmt, | ||||
|                                                           ObSelectStmt *view_stmt, | ||||
|                                                           ObIArray<int64_t> &select_offset, | ||||
|                                                           bool &is_valid) | ||||
| { | ||||
|   int ret = OB_SUCCESS; | ||||
|   is_valid = true; | ||||
|   if (OB_ISNULL(select_stmt)|| OB_ISNULL(view_stmt)) { | ||||
|     ret = OB_INVALID_ARGUMENT; | ||||
|     LOG_WARN("stmt is NULL", K(select_stmt), K(view_stmt), K(ret)); | ||||
|   } else if (!view_stmt->is_set_stmt()) { | ||||
|     // do nothing | ||||
|   } else { | ||||
|     ObSEArray<ObRawExpr*, 4> relation_exprs; | ||||
|     ObSEArray<ObRawExpr*, 4> set_op_exprs; | ||||
|     ObBitSet<> selected_set_op_idx; | ||||
|     ObStmtExprGetter visitor; | ||||
|     visitor.set_relation_scope(); | ||||
|     visitor.remove_scope(SCOPE_SELECT); | ||||
|     if (OB_FAIL(view_stmt->get_relation_exprs(relation_exprs, visitor))) { | ||||
|       LOG_WARN("failed to get relation exprs", K(ret)); | ||||
|     } else if (OB_FAIL(ObRawExprUtils::extract_set_op_exprs(relation_exprs, | ||||
|                                                             set_op_exprs))) { | ||||
|       LOG_WARN("failed to extract column ids", K(ret)); | ||||
|     } | ||||
|     for (int64_t i = 0; OB_SUCC(ret) && i < select_offset.count(); ++i) { | ||||
|       if (select_offset.at(i) != -1) { | ||||
|         selected_set_op_idx.add_member(select_offset.at(i)); | ||||
|       } | ||||
|     } | ||||
|     for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < set_op_exprs.count(); ++i) { | ||||
|       ObSetOpRawExpr *expr = static_cast<ObSetOpRawExpr*>(set_op_exprs.at(i)); | ||||
|       if (OB_ISNULL(expr)) { | ||||
|         ret = OB_ERR_UNEXPECTED; | ||||
|         LOG_WARN("unexpected null expr", K(ret), KPC(set_op_exprs.at(i))); | ||||
|       } else if (!selected_set_op_idx.has_member(expr->get_idx())) { | ||||
|         is_valid = false; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| /*@brief check_rownum_push_down检查含有rownum能否被下压 | ||||
| * 1.外层存在rownum时 | ||||
| * 如果外层存在rownum,内层是非spj时算子基本都不支持下压,如: | ||||
|  | ||||
| @ -74,6 +74,10 @@ private: | ||||
|                           bool &is_same, | ||||
|                           common::ObIArray<int64_t> &select_offset, | ||||
|                           common::ObIArray<SelectItem> &const_select_items); | ||||
|   int check_set_op_expr_reference(ObSelectStmt *select_stmt, | ||||
|                                   ObSelectStmt *view_stmt, | ||||
|                                   common::ObIArray<int64_t> &select_offset, | ||||
|                                   bool &is_contain); | ||||
|   int do_transform(ObSelectStmt *select_stmt, | ||||
|                    ObSelectStmt *view_stmt, | ||||
|                    bool need_distinct, | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 yinyj17
					yinyj17