Fix query push down and add subquery handling
This commit is contained in:
parent
49d67f8644
commit
7dcf2baa4e
@ -3084,6 +3084,23 @@ bool ObDMLStmt::has_link_table() const
|
||||
return bret;
|
||||
}
|
||||
|
||||
int ObDMLStmt::get_table_rel_ids(const TableItem &target,
|
||||
ObSqlBitSet<> &table_set) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (target.is_joined_table()) {
|
||||
const JoinedTable &cur_table = static_cast<const JoinedTable &>(target);
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < cur_table.single_table_ids_.count(); ++i) {
|
||||
if (OB_FAIL(table_set.add_member(get_table_bit_index(cur_table.single_table_ids_.at(i))))) {
|
||||
LOG_WARN("failed to add member", K(ret), K(cur_table.single_table_ids_.at(i)));
|
||||
}
|
||||
}
|
||||
} else if (OB_FAIL(table_set.add_member(get_table_bit_index(target.table_id_)))) {
|
||||
LOG_WARN("failed to add member", K(ret), K(target.table_id_));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObDMLStmt::get_relation_exprs(ObIArray<ObRawExpr*>& rel_array, int32_t ignore_scope /* = 0*/) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
@ -887,6 +887,7 @@ public:
|
||||
virtual int clear_sharable_expr_reference();
|
||||
virtual int get_from_subquery_stmts(common::ObIArray<ObSelectStmt*>& child_stmts) const;
|
||||
int is_referred_by_partitioning_expr(const ObRawExpr* expr, bool& is_referred);
|
||||
int get_table_rel_ids(const TableItem &target, ObSqlBitSet<> &table_set) const;
|
||||
int64_t get_table_size() const
|
||||
{
|
||||
return table_items_.count();
|
||||
|
@ -342,6 +342,10 @@ int ObTransformQueryPushDown::check_select_item_push_down(ObSelectStmt* select_s
|
||||
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 (OB_FAIL(check_select_item_subquery(*select_stmt, *view_stmt, check_status))) {
|
||||
LOG_WARN("failed to check select item has subquery", K(ret));
|
||||
} else if (!check_status) {
|
||||
can_be = false;
|
||||
} else if (view_stmt->is_contains_assignment() || select_stmt->is_contains_assignment()) {
|
||||
can_be = false;
|
||||
} else if (OB_FAIL(is_select_item_same(select_stmt, view_stmt, check_status, select_offset, const_select_items))) {
|
||||
@ -358,6 +362,58 @@ int ObTransformQueryPushDown::check_select_item_push_down(ObSelectStmt* select_s
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformQueryPushDown::check_select_item_subquery(ObSelectStmt &select_stmt,
|
||||
ObSelectStmt &view,
|
||||
bool &can_be)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
can_be = true;
|
||||
ObSEArray<ObRawExpr*, 4> column_exprs_from_subquery;
|
||||
ObRawExpr *expr = NULL;
|
||||
TableItem *table = NULL;
|
||||
ObSqlBitSet<> table_set;
|
||||
if (OB_UNLIKELY(1 != select_stmt.get_table_items().count())
|
||||
|| OB_ISNULL(table = select_stmt.get_table_item(0))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect select stmt", K(ret), K(select_stmt.get_from_item_size()), K(table));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < view.get_select_item_size(); ++i) {
|
||||
if (OB_ISNULL(expr = view.get_select_item(i).expr_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect null expr", K(ret));
|
||||
} else if (!expr->has_flag(CNT_SUB_QUERY)) {
|
||||
/* do nothing */
|
||||
} else if (OB_ISNULL(expr = select_stmt.get_column_expr_by_id(table->table_id_,
|
||||
i + OB_APP_MIN_COLUMN_ID))) {
|
||||
/* do nothing */
|
||||
} else if (OB_FAIL(column_exprs_from_subquery.push_back(expr))) {
|
||||
LOG_WARN("failed to push back column expr", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (column_exprs_from_subquery.empty()) {
|
||||
/* do nothing */
|
||||
} else if (OB_FAIL(select_stmt.get_table_rel_ids(*table, table_set))) {
|
||||
LOG_WARN("failed to get rel ids", K(ret));
|
||||
} else {
|
||||
ObIArray<ObQueryRefRawExpr*> &subquery_exprs = select_stmt.get_subquery_exprs();
|
||||
ObSEArray<ObDMLStmt *, 4> ignore_stmts;
|
||||
ObSEArray<ObRawExpr*, 4> column_exprs;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && can_be && i < subquery_exprs.count(); ++i) {
|
||||
column_exprs.reuse();
|
||||
if(OB_FAIL(ObTransformUtils::extract_column_exprs(subquery_exprs.at(i),
|
||||
select_stmt.get_current_level(),
|
||||
table_set, ignore_stmts,
|
||||
column_exprs))) {
|
||||
LOG_WARN("extract column exprs failed", K(ret));
|
||||
} else if (ObOptimizerUtil::overlap(column_exprs, column_exprs_from_subquery)) {
|
||||
can_be = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformQueryPushDown::check_where_condition_push_down(
|
||||
ObSelectStmt* select_stmt, ObSelectStmt* view_stmt, bool& transform_having, bool& can_be)
|
||||
{
|
||||
|
@ -56,7 +56,9 @@ private:
|
||||
int check_select_item_push_down(ObSelectStmt* select_stmt, ObSelectStmt* view_stmt,
|
||||
common::ObIArray<int64_t>& select_offset, common::ObIArray<SelectItem>& const_select_items, bool& can_be);
|
||||
|
||||
int check_select_item_has_subquery(ObSelectStmt& view, bool& has);
|
||||
int check_select_item_subquery(ObSelectStmt &select_stmt,
|
||||
ObSelectStmt &view,
|
||||
bool &can_be);
|
||||
|
||||
int adjust_stmt_hints(ObSelectStmt* select_stmt, ObSelectStmt* view_stmt);
|
||||
|
||||
|
@ -4594,6 +4594,7 @@ int ObTransformUtils::extract_column_exprs(ObDMLStmt* stmt, const int64_t stmt_l
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSEArray<ObRawExpr*, 16> relation_exprs;
|
||||
ObSEArray<ObSelectStmt*, 16> child_stmts;
|
||||
bool is_stack_overflow = false;
|
||||
if (OB_ISNULL(stmt)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
@ -4609,7 +4610,19 @@ int ObTransformUtils::extract_column_exprs(ObDMLStmt* stmt, const int64_t stmt_l
|
||||
LOG_WARN("failed to get relation exprs", K(ret));
|
||||
} else if (OB_FAIL(SMART_CALL(extract_column_exprs(relation_exprs, stmt_level, table_set, ignore_stmts, columns)))) {
|
||||
LOG_WARN("failed to extract column exprs", K(ret));
|
||||
} else { /*do nothing*/
|
||||
} else if (OB_FAIL(stmt->get_from_subquery_stmts(child_stmts))) {
|
||||
LOG_WARN("get child stmt failed", K(ret));
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) {
|
||||
ObSelectStmt* child_stmt = child_stmts.at(i);
|
||||
if (OB_ISNULL(child_stmt)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("invalid stmt", K(ret));
|
||||
} else if (OB_FAIL(SMART_CALL(extract_column_exprs(child_stmt, stmt_level, table_set,
|
||||
ignore_stmts, columns)))) {
|
||||
LOG_WARN("failed to extract column exprs", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -6545,7 +6558,7 @@ int ObTransformUtils::convert_select_expr_to_column_expr(const common::ObIArray<
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("failed to find select expr inner stmt", K(ret));
|
||||
} else if (OB_ISNULL(col = outer_stmt.get_column_expr_by_id(table_id, column_id))) {
|
||||
LOG_WARN("failed to get column expr by id", K(ret));
|
||||
//do nothing
|
||||
} else if (OB_FAIL(column_exprs.push_back(col))) {
|
||||
LOG_WARN("failed to push back column expr", K(ret));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user