[Commits] d347659: An optimization of the code for mdev-11953.
revision-id: d347659fa0ca044074ab44497b1373053ca79f3d (mariadb-10.3.6-7-gd347659) parent(s): 549bcceefd94e8700c9e629bdd2c2f5a73d2459b author: Igor Babaev committer: Igor Babaev timestamp: 2018-05-24 21:41:51 -0700 message: An optimization of the code for mdev-11953. This patch eliminates the usage of the stack last_select_stack in the parser. Now the field st_select_lex::first_nested is used to perform the actions that were implemented with last_select_stack. --- sql/sql_lex.cc | 55 ++++++++++++++++++----------------------------------- sql/sql_lex.h | 36 ++++++++++++++++++----------------- sql/sql_yacc.yy | 47 ++++++++++++++++++++------------------------- sql/sql_yacc_ora.yy | 47 ++++++++++++++++++++------------------------- 4 files changed, 80 insertions(+), 105 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 55e76c7..bd1d780 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -5330,12 +5330,12 @@ LEX::wrap_unit_into_derived(SELECT_LEX_UNIT *unit) DBUG_RETURN(NULL); } -SELECT_LEX *LEX::link_selects_chain_down(SELECT_LEX *sel) +SELECT_LEX *LEX::wrap_select_chain_into_derived(SELECT_LEX *sel) { SELECT_LEX *dummy_select; SELECT_LEX_UNIT *unit; Table_ident *ti; - DBUG_ENTER("LEX::link_selects_chain_down"); + DBUG_ENTER("LEX::wrap_select_chain_into_derived"); if (!(dummy_select= alloc_select(TRUE))) DBUG_RETURN(NULL); @@ -5525,44 +5525,27 @@ bool LEX::push_context(Name_resolution_context *context) } -bool LEX::push_new_select(SELECT_LEX *last) +SELECT_LEX *LEX::create_priority_nest(SELECT_LEX *first_in_nest) { - DBUG_ENTER("LEX::push new_select"); - DBUG_PRINT("info", ("Push last select: %p (%d)", - last, last->select_number)); - bool res= last_select_stack.push_front(last, thd->mem_root); - DBUG_RETURN(res); -} - - -bool check_intersect_prefix(SELECT_LEX* first_in_unit) -{ - SELECT_LEX *sel; - for (sel= first_in_unit->next_select(); - sel && sel->linkage == INTERSECT_TYPE; - sel= sel->next_select()) - ; - return (sel == NULL); + DBUG_ENTER("LEX::create_priority_nest"); + DBUG_ASSERT(first_in_nest->first_nested); + enum sub_select_type wr_unit_type= first_in_nest->linkage; + bool wr_distinct= first_in_nest->distinct; + SELECT_LEX *attach_to= first_in_nest->first_nested; + attach_to->cut_next(); + SELECT_LEX *wrapper= wrap_select_chain_into_derived(first_in_nest); + if (wrapper) + { + first_in_nest->first_nested= NULL; + wrapper->set_linkage_and_distinct(wr_unit_type, wr_distinct); + wrapper->first_nested= attach_to->first_nested; + wrapper->set_master_unit(attach_to->master_unit()); + attach_to->link_neighbour(wrapper); + } + DBUG_RETURN(wrapper); } -SELECT_LEX *LEX::pop_new_select_and_wrap() -{ - DBUG_ENTER("LEX::pop_new_select_and_wrap"); - SELECT_LEX *sel; - SELECT_LEX *last= pop_new_select(); - SELECT_LEX *first= last->next_select(); - last->cut_next(); - enum sub_select_type op= first->linkage; - bool ds= first->distinct; - if (!(sel= link_selects_chain_down(first))) - DBUG_RETURN(NULL); - last->link_neighbour(sel); - sel->set_linkage_and_distinct(op, ds); - sel->set_master_unit(last->master_unit()); - DBUG_RETURN(sel); -} - /** Checks if we need finish "automatic brackets" mode diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f715fdd..2a94d96 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -82,8 +82,6 @@ inline int cmp_unit_op(enum sub_select_type op1, enum sub_select_type op2) return (op1 == INTERSECT_TYPE ? 1 : 0) - (op2 == INTERSECT_TYPE ? 1 : 0); } -bool check_intersect_prefix(SELECT_LEX* first_in_unit); - enum unit_common_op {OP_MIX, OP_UNION, OP_INTERSECT, OP_EXCEPT}; enum enum_view_suid @@ -887,6 +885,23 @@ class Field_pair :public Sql_alloc class st_select_lex: public st_select_lex_node { public: + /* + Currently the field first_nested is used only by parser. + It containa either a reference to the first select + of the nest of selects to which 'this' belongs to, or + in the case of priority jump it contains a reference to + the select to which the priority nest has to be attached to. + If there is no priority jump then the first select of the + nest contains the reference to itself in first_nested. + Example: + select1 union select2 intersect select + Here we have a priority jump at select2. + So select2->first_nested points to select1, + while select3->first_nested points to select2 and + select1->first_nested points to select1. + */ + st_select_lex *first_nested; + Name_resolution_context context; LEX_CSTRING db; Item *where, *having; /* WHERE & HAVING clauses */ @@ -2881,7 +2896,6 @@ struct LEX: public Query_tables_list required a local context, the parser pops the top-most context. */ List<Name_resolution_context> context_stack; - List<SELECT_LEX> last_select_stack; SELECT_LEX *select_stack[MAX_SELECT_NESTING]; uint select_stack_top; @@ -3251,17 +3265,6 @@ struct LEX: public Query_tables_list DBUG_VOID_RETURN; } - bool push_new_select(SELECT_LEX *last); - - SELECT_LEX *pop_new_select() - { - DBUG_ENTER("LEX::pop_new_select"); - SELECT_LEX* last= last_select_stack.pop(); - DBUG_PRINT("info", ("Pop last elect: %p (%d)", - last, last->select_number)); - DBUG_RETURN(last); - } - SELECT_LEX *select_stack_head() { if (likely(select_stack_top)) @@ -3269,7 +3272,6 @@ struct LEX: public Query_tables_list return NULL; } - bool push_select(SELECT_LEX *select_lex) { DBUG_ENTER("LEX::push_select"); @@ -3982,10 +3984,10 @@ struct LEX: public Query_tables_list SELECT_LEX *alloc_select(bool is_select); SELECT_LEX_UNIT *create_unit(SELECT_LEX*); SELECT_LEX *wrap_unit_into_derived(SELECT_LEX_UNIT *unit); - SELECT_LEX *link_selects_chain_down(SELECT_LEX *sel); + SELECT_LEX *wrap_select_chain_into_derived(SELECT_LEX *sel); bool main_select_push(); bool insert_select_hack(SELECT_LEX *sel); - SELECT_LEX *pop_new_select_and_wrap(); + SELECT_LEX *create_priority_nest(SELECT_LEX *first_in_nest); void set_main_unit(st_select_lex_unit *u) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 491874b..7117865 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9182,16 +9182,13 @@ query_primary: query_primary_parens: '(' query_expression_unit { - SELECT_LEX *last= $2->pre_last_parse->next_select(); - int cmp= cmp_unit_op($2->first_select()->next_select()->linkage, - last->linkage); - if (cmp < 0) + SELECT_LEX *first_in_nest= + $2->pre_last_parse->next_select()->first_nested; + if (first_in_nest->first_nested != first_in_nest) { - if (!check_intersect_prefix($2->first_select())) - { - if (Lex->pop_new_select_and_wrap() == NULL) - MYSQL_YYABORT; - } + /* There is a priority jump starting from first_in_nest */ + if (Lex->create_priority_nest(first_in_nest) == NULL) + MYSQL_YYABORT; } Lex->push_select($2->fake_select_lex); } @@ -9275,6 +9272,7 @@ query_expression_unit: } sel1->link_neighbour(sel2); sel2->set_linkage_and_distinct($2.unit_type, $2.distinct); + sel2->first_nested= sel1->first_nested= sel1; $$= Lex->create_unit(sel1); $$->pre_last_parse= sel1; if ($$ == NULL) @@ -9298,23 +9296,23 @@ query_expression_unit: int cmp= cmp_unit_op($2.unit_type, last->linkage); if (cmp == 0) { - // do nothing, this part will be just connected + sel1->first_nested= last->first_nested; } else if (cmp > 0) { - // Store beginning and continue to connect parts - if (Lex->push_new_select($1->pre_last_parse)) - MYSQL_YYABORT; + last->first_nested= $1->pre_last_parse; + sel1->first_nested= last; } else /* cmp < 0 */ { - // wrap stored part in a select, then continue to connect parts - if (!check_intersect_prefix($1->first_select())) + SELECT_LEX *first_in_nest= last->first_nested; + if (first_in_nest->first_nested != first_in_nest) { - if ((last= Lex->pop_new_select_and_wrap()) == NULL) + /* There is a priority jump starting from first_in_nest */ + if ((last= Lex->create_priority_nest(first_in_nest)) == NULL) MYSQL_YYABORT; - last->set_master_unit($1); } + sel1->first_nested= last->first_nested; } last->link_neighbour(sel1); sel1->set_master_unit($1); @@ -9373,16 +9371,13 @@ query_expression_body: } | query_expression_unit { - SELECT_LEX *last= $1->pre_last_parse->next_select(); - int cmp= cmp_unit_op($1->first_select()->next_select()->linkage, - last->linkage); - if (cmp < 0) + SELECT_LEX *first_in_nest= + $1->pre_last_parse->next_select()->first_nested; + if (first_in_nest->first_nested != first_in_nest) { - if (!check_intersect_prefix($1->first_select())) - { - if (Lex->pop_new_select_and_wrap() == NULL) - MYSQL_YYABORT; - } + /* There is a priority jump starting from first_in_nest */ + if (Lex->create_priority_nest(first_in_nest) == NULL) + MYSQL_YYABORT; } Lex->push_select($1->fake_select_lex); } diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 069fa0a..8bf09df 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -9000,16 +9000,13 @@ query_primary: query_primary_parens: '(' query_expression_unit { - SELECT_LEX *last= $2->pre_last_parse->next_select(); - int cmp= cmp_unit_op($2->first_select()->next_select()->linkage, - last->linkage); - if (cmp < 0) + SELECT_LEX *first_in_nest= + $2->pre_last_parse->next_select()->first_nested; + if (first_in_nest->first_nested != first_in_nest) { - if (!check_intersect_prefix($2->first_select())) - { - if (Lex->pop_new_select_and_wrap() == NULL) - MYSQL_YYABORT; - } + /* There is a priority jump starting from first_in_nest */ + if (Lex->create_priority_nest(first_in_nest) == NULL) + MYSQL_YYABORT; } Lex->push_select($2->fake_select_lex); } @@ -9093,6 +9090,7 @@ query_expression_unit: } sel1->link_neighbour(sel2); sel2->set_linkage_and_distinct($2.unit_type, $2.distinct); + sel2->first_nested= sel1->first_nested= sel1; $$= Lex->create_unit(sel1); $$->pre_last_parse= sel1; if ($$ == NULL) @@ -9116,23 +9114,23 @@ query_expression_unit: int cmp= cmp_unit_op($2.unit_type, last->linkage); if (cmp == 0) { - // do nothing, this part will be just connected + sel1->first_nested= last->first_nested; } else if (cmp > 0) { - // Store beginning and continue to connect parts - if (Lex->push_new_select($1->pre_last_parse)) - MYSQL_YYABORT; + last->first_nested= $1->pre_last_parse; + sel1->first_nested= last; } else /* cmp < 0 */ { - // wrap stored part in a select, then continue to connect parts - if (!check_intersect_prefix($1->first_select())) + SELECT_LEX *first_in_nest= last->first_nested; + if (first_in_nest->first_nested != first_in_nest) { - if ((last= Lex->pop_new_select_and_wrap()) == NULL) + /* There is a priority jump starting from first_in_nest */ + if ((last= Lex->create_priority_nest(first_in_nest)) == NULL) MYSQL_YYABORT; - last->set_master_unit($1); } + sel1->first_nested= last->first_nested; } last->link_neighbour(sel1); sel1->set_master_unit($1); @@ -9191,16 +9189,13 @@ query_expression_body: } | query_expression_unit { - SELECT_LEX *last= $1->pre_last_parse->next_select(); - int cmp= cmp_unit_op($1->first_select()->next_select()->linkage, - last->linkage); - if (cmp < 0) + SELECT_LEX *first_in_nest= + $1->pre_last_parse->next_select()->first_nested; + if (first_in_nest->first_nested != first_in_nest) { - if (!check_intersect_prefix($1->first_select())) - { - if (Lex->pop_new_select_and_wrap() == NULL) - MYSQL_YYABORT; - } + /* There is a priority jump starting from first_in_nest */ + if (Lex->create_priority_nest(first_in_nest) == NULL) + MYSQL_YYABORT; } Lex->push_select($1->fake_select_lex); }
participants (1)
-
IgorBabaev