提交 af7a161c 编写于 作者: O obdev 提交者: wangzelin.wzl

[CP] fix join eliminate bug

上级 577e69c1
......@@ -1998,7 +1998,80 @@ int ObOptimizerUtil::get_subquery_id(const ObDMLStmt* upper_stmt, const ObSelect
return ret;
}
int ObOptimizerUtil::is_table_on_null_side(const ObDMLStmt* stmt, uint64_t table_id, bool& is_on_null_side)
/**
* @brief
* given source and target table id, try to find its lowest common joined table
* then check if the source table is on the null side of the joined table
* @param stmt
* @param source_table_id
* @param target_table_id
* @param is_on_null_side
* @return int
*/
int ObOptimizerUtil::is_table_on_null_side_of_parent(
const ObDMLStmt *stmt, uint64_t source_table_id, uint64_t target_table_id, bool &is_on_null_side)
{
int ret = OB_SUCCESS;
is_on_null_side = false;
if (OB_ISNULL(stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("upper_stmt is null", K(ret));
} else {
JoinedTable *common_joined_table = NULL;
for (int64_t i = 0; OB_SUCC(ret) && OB_ISNULL(common_joined_table) && i < stmt->get_joined_tables().count(); ++i) {
JoinedTable *joined_table = stmt->get_joined_tables().at(i);
bool is_source_in_joined_table = false;
if (OB_ISNULL(joined_table)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_FAIL(
find_common_joined_table(joined_table, source_table_id, target_table_id, common_joined_table))) {
LOG_WARN("failed to find target joined table", K(ret));
} else if (common_joined_table != NULL &&
OB_FAIL(is_table_on_null_side_recursively(
common_joined_table, source_table_id, is_source_in_joined_table, is_on_null_side))) {
LOG_WARN("Check for generated table on null side recursively fails", K(is_on_null_side), K(i), K(ret));
}
}
}
return ret;
}
int ObOptimizerUtil::find_common_joined_table(
JoinedTable *joined_table, uint64_t source_table_id, uint64_t target_table_id, JoinedTable *&target_joined_table)
{
int ret = OB_SUCCESS;
TableItem *left_table = NULL;
TableItem *right_table = NULL;
if (OB_ISNULL(joined_table)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (OB_ISNULL(left_table = joined_table->left_table_) || OB_ISNULL(right_table = joined_table->right_table_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(left_table), K(right_table));
} else if (is_contain(joined_table->single_table_ids_, source_table_id) &&
is_contain(joined_table->single_table_ids_, target_table_id)) {
target_joined_table = joined_table;
JoinedTable *left_common_table = NULL;
JoinedTable *right_common_table = NULL;
if (left_table->is_joined_table() &&
OB_FAIL(find_common_joined_table(
static_cast<JoinedTable *>(left_table), source_table_id, target_table_id, left_common_table))) {
LOG_WARN("failed to find left common joined table", K(ret));
} else if (left_common_table != NULL) {
target_joined_table = left_common_table;
} else if (right_table->is_joined_table() &&
OB_FAIL(find_common_joined_table(
static_cast<JoinedTable *>(right_table), source_table_id, target_table_id, right_common_table))) {
LOG_WARN("failed to find right common joined table", K(ret));
} else if (right_common_table != NULL) {
target_joined_table = right_common_table;
}
}
return ret;
}
int ObOptimizerUtil::is_table_on_null_side(const ObDMLStmt *stmt, uint64_t table_id, bool &is_on_null_side)
{
int ret = OB_SUCCESS;
is_on_null_side = false;
......
......@@ -304,8 +304,13 @@ public:
static int is_table_on_null_side_recursively(
const TableItem* table_item, uint64_t table_id, bool& found, bool& is_on_null_side);
static int get_referenced_columns(const ObDMLStmt* stmt, const uint64_t table_id,
const common::ObIArray<ObRawExpr*>& keys, common::ObIArray<ObRawExpr*>& columns);
static int is_table_on_null_side_of_parent(
const ObDMLStmt *stmt, uint64_t source_table_id, uint64_t target_table_id, bool &is_on_null_side);
static int find_common_joined_table(
JoinedTable *joined_table, uint64_t source_table_id, uint64_t target_table_id, JoinedTable *&target_joined_table);
static int get_referenced_columns(const ObDMLStmt *stmt, const uint64_t table_id,
const common::ObIArray<ObRawExpr *> &keys, common::ObIArray<ObRawExpr *> &columns);
static int get_non_referenced_columns(const ObDMLStmt* stmt, const uint64_t table_id,
const common::ObIArray<ObRawExpr*>& keys, common::ObIArray<ObRawExpr*>& columns);
......
......@@ -97,6 +97,7 @@ int ObTransformJoinElimination::eliminate_join_self_foreign_key(ObDMLStmt *stmt,
LOG_WARN("eliminate join in joined table failed", K(ret));
} else {
trans_happened = from_happedend | joined_happedend;
LOG_TRACE("succ to do self foreign key elimination", K(from_happedend), K(joined_happedend));
}
return ret;
}
......@@ -115,23 +116,27 @@ int ObTransformJoinElimination::eliminate_join_in_from_base_table(ObDMLStmt* stm
LOG_WARN("failed to get equal set conditions", K(ret));
} else if (OB_FAIL(extract_candi_table(stmt, stmt->get_from_items(), candi_tables, child_candi_tables))) {
LOG_WARN("failed to extract candi tables", K(ret));
} else if (OB_FAIL(eliminate_candi_tables(stmt, conds, candi_tables, child_candi_tables, trans_happened))) {
} else if (OB_FAIL(eliminate_candi_tables(stmt, conds, candi_tables, child_candi_tables, true, trans_happened))) {
LOG_WARN("failed to eliminate candi tables", K(ret));
}
return ret;
}
int ObTransformJoinElimination::do_join_elimination_self_key(ObDMLStmt* stmt, TableItem* source_table,
TableItem* target_table, bool& trans_happened,
EqualSets* equal_sets) // default value NULL
int ObTransformJoinElimination::do_join_elimination_self_key(ObDMLStmt *stmt, TableItem *source_table,
TableItem *target_table, bool is_from_base_table, bool &trans_happened, EqualSets *equal_sets /*= NULL*/)
{
int ret = OB_SUCCESS;
trans_happened = false;
ObStmtMapInfo stmt_map_info;
bool can_be_eliminated = false;
bool is_on_null_side = false;
if (OB_ISNULL(stmt) || OB_ISNULL(ctx_) || OB_ISNULL(source_table) || OB_ISNULL(target_table)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(stmt), K(ctx_), K(ret));
} else if (OB_FAIL(check_on_null_side(
stmt, source_table->table_id_, target_table->table_id_, is_from_base_table, is_on_null_side))) {
LOG_WARN("failed to check table on null side", K(ret));
} else if (OB_FAIL(ObTransformUtils::check_loseless_join(stmt,
ctx_,
source_table,
......@@ -139,6 +144,7 @@ int ObTransformJoinElimination::do_join_elimination_self_key(ObDMLStmt* stmt, Ta
ctx_->session_info_,
ctx_->schema_checker_,
stmt_map_info,
is_on_null_side,
can_be_eliminated,
equal_sets))) {
LOG_WARN("failed to check whether transformation is possible", K(ret));
......@@ -157,8 +163,29 @@ int ObTransformJoinElimination::do_join_elimination_self_key(ObDMLStmt* stmt, Ta
return ret;
}
int ObTransformJoinElimination::do_join_elimination_foreign_key(ObDMLStmt* stmt, const TableItem* child_table,
const TableItem* parent_table, const ObForeignKeyInfo* foreign_key_info)
int ObTransformJoinElimination::check_on_null_side(
ObDMLStmt *stmt, uint64_t source_table_id, uint64_t target_table_id, bool is_from_base_table, bool &is_on_null_side)
{
int ret = OB_SUCCESS;
is_on_null_side = false;
if (OB_ISNULL(stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret));
} else if (is_from_base_table) {
if (OB_FAIL(ObOptimizerUtil::is_table_on_null_side(stmt, source_table_id, is_on_null_side))) {
LOG_WARN("failed to check table is on null side", K(ret));
}
} else {
if (OB_FAIL(ObOptimizerUtil::is_table_on_null_side_of_parent(
stmt, source_table_id, target_table_id, is_on_null_side))) {
LOG_WARN("failed to check table is on null side", K(ret));
}
}
return ret;
}
int ObTransformJoinElimination::do_join_elimination_foreign_key(ObDMLStmt *stmt, const TableItem *child_table,
const TableItem *parent_table, const ObForeignKeyInfo *foreign_key_info)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt)) {
......@@ -1706,7 +1733,8 @@ int ObTransformJoinElimination::eliminate_join_in_joined_table(ObDMLStmt* stmt,
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(eliminate_candi_tables(stmt, inner_join_conds, other_tables, child_candi_tables, is_happened))) {
} else if (OB_FAIL(eliminate_candi_tables(
stmt, inner_join_conds, other_tables, child_candi_tables, false, is_happened))) {
LOG_WARN("failed to eliminate candi tables", K(ret));
} else if (OB_FAIL(append(outer_join_tables, other_tables))) {
LOG_WARN("failed to append tables", K(ret));
......@@ -1724,8 +1752,9 @@ int ObTransformJoinElimination::eliminate_join_in_joined_table(ObDMLStmt* stmt,
return ret;
}
int ObTransformJoinElimination::eliminate_candi_tables(ObDMLStmt* stmt, ObIArray<ObRawExpr*>& conds,
ObIArray<TableItem*>& candi_tables, ObIArray<TableItem*>& child_candi_tables, bool& trans_happened)
int ObTransformJoinElimination::eliminate_candi_tables(ObDMLStmt *stmt, ObIArray<ObRawExpr *> &conds,
ObIArray<TableItem *> &candi_tables, ObIArray<TableItem *> &child_candi_tables, bool is_from_base_table,
bool &trans_happened)
{
int ret = OB_SUCCESS;
trans_happened = false;
......@@ -1751,7 +1780,7 @@ int ObTransformJoinElimination::eliminate_candi_tables(ObDMLStmt* stmt, ObIArray
} 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))) {
stmt, candi_tables.at(i), candi_tables.at(j), is_from_base_table, is_happened, equal_sets))) {
LOG_WARN("failed to eliminate self key join in base table", K(ret));
} else if (!is_happened) {
/*do nothing*/
......@@ -1768,8 +1797,12 @@ int ObTransformJoinElimination::eliminate_candi_tables(ObDMLStmt* stmt, ObIArray
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))) {
} else if (OB_FAIL(do_join_elimination_self_key(stmt,
child_candi_tables.at(j),
candi_tables.at(i),
is_from_base_table,
is_happened,
equal_sets))) {
LOG_WARN("failed to do join elimination erlf key", K(ret));
} else if (!is_happened) {
/*do nothing*/
......
......@@ -69,7 +69,7 @@ private:
/**
* @brief eliminate_join_self_key
* cases that can be eliminated for self key join
* 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
......@@ -98,11 +98,14 @@ private:
int eliminate_join_in_joined_table(ObDMLStmt* stmt, TableItem*& table_item, ObIArray<TableItem*>& child_candi_tables,
ObIArray<ObRawExpr*>& trans_conditions, bool& trans_happened);
int eliminate_candi_tables(ObDMLStmt* stmt, ObIArray<ObRawExpr*>& conds, ObIArray<TableItem*>& candi_tables,
ObIArray<TableItem*>& child_candi_tables, bool& trans_happened);
int eliminate_candi_tables(ObDMLStmt *stmt, ObIArray<ObRawExpr *> &conds, ObIArray<TableItem *> &candi_tables,
ObIArray<TableItem *> &child_candi_tables, bool is_from_base_table, bool &trans_happened);
int do_join_elimination_self_key(ObDMLStmt* stmt, TableItem* source_table, TableItem* target_table,
bool& trans_happened, EqualSets* equal_sets = NULL);
int check_on_null_side(ObDMLStmt *stmt, uint64_t source_table_id, uint64_t target_table_id, bool is_from_base_table,
bool &is_on_null_side);
int do_join_elimination_self_key(ObDMLStmt *stmt, TableItem *source_table, TableItem *target_table,
bool is_from_base_table, bool &trans_happened, EqualSets *equal_sets = NULL);
int do_join_elimination_foreign_key(ObDMLStmt* stmt, const TableItem* child_table, const TableItem* parent_table,
const share::schema::ObForeignKeyInfo* foreign_key_info);
......
......@@ -4726,17 +4726,18 @@ bool ObTransformUtils::is_subarray(const ObRelIds& table_ids, const common::ObIA
return bool_ret;
}
int ObTransformUtils::check_loseless_join(ObDMLStmt* stmt, ObTransformerCtx* ctx, TableItem* source_table,
TableItem* target_table, ObSQLSessionInfo* session_info, ObSchemaChecker* schema_checker,
ObStmtMapInfo& stmt_map_info, bool& is_loseless,
EqualSets* input_equal_sets) // default value NULL
int ObTransformUtils::check_loseless_join(ObDMLStmt *stmt, ObTransformerCtx *ctx, TableItem *source_table,
TableItem *target_table, ObSQLSessionInfo *session_info, ObSchemaChecker *schema_checker,
ObStmtMapInfo &stmt_map_info, bool is_on_null_side, bool &is_loseless,
EqualSets *input_equal_sets /*= NULL*/)
{
int ret = OB_SUCCESS;
bool is_contain = false;
bool source_unique = false;
bool target_unique = false;
ObSEArray<ObRawExpr*, 16> source_exprs;
ObSEArray<ObRawExpr*, 16> target_exprs;
ObSEArray<ObRawExpr *, 16> source_exprs;
ObSEArray<ObRawExpr *, 16> target_exprs;
ObSEArray<ObRawExpr *, 8> target_tab_cols;
is_loseless = false;
if (OB_ISNULL(stmt) || OB_ISNULL(source_table) || OB_ISNULL(target_table) || OB_ISNULL(schema_checker)) {
ret = OB_ERR_UNEXPECTED;
......@@ -4754,6 +4755,10 @@ int ObTransformUtils::check_loseless_join(ObDMLStmt* stmt, ObTransformerCtx* ctx
target_exprs,
input_equal_sets))) {
LOG_WARN("failed to extract lossless join columns", K(ret));
} else if (OB_FAIL(stmt->get_column_exprs(target_table->table_id_, target_tab_cols))) {
LOG_WARN("failed to get column exprs", K(ret));
} else if (is_on_null_side && !target_tab_cols.empty() && target_exprs.empty()) {
is_loseless = false;
} else if (OB_FAIL(ObTransformUtils::check_exprs_unique(
*stmt, source_table, source_exprs, session_info, schema_checker, source_unique))) {
LOG_WARN("failed to check exprs unique", K(ret));
......
......@@ -548,9 +548,10 @@ public:
static bool is_subarray(const ObRelIds& table_ids, const common::ObIArray<ObRelIds>& other);
static int check_loseless_join(ObDMLStmt* stmt, ObTransformerCtx* ctx, TableItem* source_table,
TableItem* target_table, ObSQLSessionInfo* session_info, ObSchemaChecker* schema_checker,
ObStmtMapInfo& stmt_map_info, bool& is_loseless, EqualSets* input_equal_sets = NULL);
static int check_loseless_join(ObDMLStmt *stmt, ObTransformerCtx *ctx, TableItem *source_table,
TableItem *target_table, ObSQLSessionInfo *session_info, ObSchemaChecker *schema_checker,
ObStmtMapInfo &stmt_map_info, bool is_on_null_side, bool &is_loseless, EqualSets *input_equal_sets = NULL);
static int check_relations_containment(ObDMLStmt* stmt, const common::ObIArray<TableItem*>& source_rels,
const common::ObIArray<TableItem*>& target_rels, common::ObIArray<ObStmtMapInfo>& stmt_map_infos,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册