diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result index ae7bf684b33..d5fdacd2609 100644 --- a/mysql-test/main/opt_trace.result +++ b/mysql-test/main/opt_trace.result @@ -11720,6 +11720,16 @@ UPDATE t, v SET t.b = t.a, t.a = v.c WHERE v.c < t.a { ] } }, + { + "join_preparation": { + "select_id": "fake", + "steps": [ + { + "expanded_query": "select c AS c from dual" + } + ] + } + }, { "join_preparation": { "select_id": 1, @@ -11967,16 +11977,6 @@ UPDATE t, v SET t.b = t.a, t.a = v.c WHERE v.c < t.a { "steps": [] } }, - { - "join_preparation": { - "select_id": "fake", - "steps": [ - { - "expanded_query": "select c AS c from dual" - } - ] - } - }, { "join_optimization": { "select_id": "fake", diff --git a/mysql-test/suite/federated/federatedx_create_handlers.result b/mysql-test/suite/federated/federatedx_create_handlers.result index 669a8fc6d09..e4e7a8a3679 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.result +++ b/mysql-test/suite/federated/federatedx_create_handlers.result @@ -572,8 +572,8 @@ CREATE TABLE federated.t2 ( a varchar(16) NOT NULL default '' ) DEFAULT CHARSET=latin1; -INSERT INTO federated.t1 VALUES ('abc'), ('bcd'), ('cde'); -INSERT INTO federated.t2 VALUES ('abc'), ('bcd'), ('cde'), ('def'), ('efg'); +INSERT INTO federated.t1 VALUES ('bcd'), ('abc'), ('cde'); +INSERT INTO federated.t2 VALUES ('cde'), ('efg'), ('abc'), ('bcd'), ('def'); connection master; CREATE TABLE federated.t1 ( a varchar(10) @@ -617,10 +617,10 @@ NULL UNION RESULT ALL NULL NULL NULL NULL NULL SELECT * from federated.t1 UNION ALL SELECT * from federated.t2; a abc -bcd -cde abc bcd +bcd +cde cde def efg @@ -730,10 +730,10 @@ SELECT * FROM (SELECT * FROM federated.t1 UNION ALL SELECT * FROM federated.t2) q; a abc -bcd -cde abc bcd +bcd +cde cde def efg @@ -861,12 +861,12 @@ SELECT * FROM federated.t1 EXCEPT SELECT * FROM t4 INTERSECT SELECT * FROM federated.t2; a -t3_myisam1 -t3_myisam2 -t3_myisam3 abc bcd cde +t3_myisam1 +t3_myisam2 +t3_myisam3 EXPLAIN SELECT * FROM t3 UNION ALL SELECT * FROM federated.t1 EXCEPT SELECT * FROM t4 INTERSECT @@ -915,13 +915,13 @@ SELECT * FROM federated.t2) UNION ALL SELECT * FROM federated.t1; a abc +abc bcd +bcd +cde cde def efg -abc -bcd -cde EXPLAIN (SELECT * FROM federated.t1 UNION SELECT * FROM federated.t2) UNION ALL (SELECT * FROM federated.t1 UNION SELECT * FROM federated.t2); id select_type table type possible_keys key key_len ref rows Extra @@ -930,14 +930,14 @@ NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL (SELECT * FROM federated.t1 UNION SELECT * FROM federated.t2); a abc -bcd -cde -def -efg abc bcd +bcd +cde cde def +def +efg efg # Union of tables containing different INT data types connection slave; @@ -955,31 +955,31 @@ CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t12'; # Entire UNION pushdown SELECT a FROM federated.t12 UNION ALL SELECT a FROM federated.t11; a +-1 +-32678 +0 0 1 32767 --32678 --1 -0 EXPLAIN SELECT a FROM federated.t12 UNION ALL SELECT a FROM federated.t11; id select_type table type possible_keys key key_len ref rows Extra NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL SELECT a FROM federated.t11 UNION SELECT a FROM federated.t12; a --32678 -1 +-32678 0 1 32767 # Partial pushdown of SELECTs composing the UNION SELECT a FROM federated.t12 UNION SELECT a FROM federated.t11 UNION SELECT 123; a +-1 +-32678 0 1 -32767 --32678 --1 123 +32767 EXPLAIN SELECT a FROM federated.t12 UNION SELECT a FROM federated.t11 UNION SELECT 123; @@ -993,9 +993,9 @@ SELECT 1 UNION ALL SELECT a FROM federated.t11 EXCEPT SELECT 0; a +-1 -32678 32767 --1 # Union of tables containing different string data types connection slave; CREATE TABLE federated.t13 (a CHAR(6)); @@ -1011,9 +1011,9 @@ ENGINE="FEDERATED" CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t14'; SELECT * FROM federated.t13 UNION SELECT * FROM federated.t14; a +common t13abc t13xx -common t14abcde t14xyzzz EXPLAIN SELECT * FROM federated.t13 UNION SELECT * FROM federated.t14; @@ -1021,12 +1021,12 @@ id select_type table type possible_keys key key_len ref rows Extra NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL SELECT * FROM federated.t14 UNION ALL SELECT * FROM federated.t13; a -t14abcde -t14xyzzz +common common t13abc t13xx -common +t14abcde +t14xyzzz SELECT * FROM federated.t14 UNION SELECT * FROM federated.t13 UNION SELECT '123456789000'; @@ -1049,10 +1049,10 @@ SELECT * FROM federated.t13 UNION SELECT '123456789000' UNION SELECT * FROM federated.t14; a +123456789000 +common t13abc t13xx -common -123456789000 t14abcde t14xyzzz # CREATE TABLE .. AS from a pushed UNION @@ -1084,6 +1084,61 @@ a -1 -32678 32767 +# +# MDEV-30828 ORDER BY clause using an integer (positional argument) +# +SELECT a FROM federated.t1 UNION SELECT a FROM federated.t2 ORDER BY 1; +a +abc +bcd +cde +def +efg +SELECT a FROM federated.t1 UNION ALL SELECT a FROM federated.t2 ORDER BY a DESC; +a +efg +def +cde +cde +bcd +bcd +abc +abc +# Check handling of incorrect ORDER BY clause +SELECT a FROM federated.t1 UNION SELECT a FROM federated.t2 ORDER BY 2; +ERROR 42S22: Unknown column '2' in 'order clause' +PREPARE stmt FROM +"SELECT a FROM federated.t1 UNION ALL SELECT a FROM federated.t2 ORDER BY 2"; +ERROR 42S22: Unknown column '2' in 'order clause' +SELECT a FROM federated.t1 UNION ALL SELECT a FROM federated.t2 ORDER BY 2,1,3; +ERROR 42S22: Unknown column '2' in 'order clause' +SELECT a FROM federated.t1 UNION ALL SELECT a FROM federated.t2 ORDER BY t1.a; +ERROR 42000: Table 't1' from one of the SELECTs cannot be used in ORDER clause +SELECT * from federated.t1 INTERSECT +SELECT * from federated.t2 UNION ALL +SELECT * from federated.t2 EXCEPT +SELECT * from federated.t1 +ORDER BY 1; +a +def +efg +SELECT * from federated.t1 INTERSECT +SELECT * from federated.t2 UNION ALL +SELECT * from federated.t2 EXCEPT +SELECT * from federated.t1 +ORDER BY 3; +ERROR 42S22: Unknown column '3' in 'order clause' +# UNION of mixed Federated/MyISAM tables, pushing parts of UNIONs +SELECT * FROM federated.t1 UNION SELECT * FROM t3 ORDER BY a; +a +abc +bcd +cde +t3_myisam1 +t3_myisam2 +t3_myisam3 +SELECT * FROM federated.t1 UNION SELECT * FROM t3 ORDER BY 2; +ERROR 42S22: Unknown column '2' in 'order clause' connection master; DROP TABLES federated.t1, federated.t2, t3, t4, t5, t6, federated.t11, federated.t12, federated.t13, federated.t14; diff --git a/mysql-test/suite/federated/federatedx_create_handlers.test b/mysql-test/suite/federated/federatedx_create_handlers.test index d4222087ea7..d183ee0bc2d 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.test +++ b/mysql-test/suite/federated/federatedx_create_handlers.test @@ -398,8 +398,8 @@ CREATE TABLE federated.t2 ( ) DEFAULT CHARSET=latin1; -INSERT INTO federated.t1 VALUES ('abc'), ('bcd'), ('cde'); -INSERT INTO federated.t2 VALUES ('abc'), ('bcd'), ('cde'), ('def'), ('efg'); +INSERT INTO federated.t1 VALUES ('bcd'), ('abc'), ('cde'); +INSERT INTO federated.t2 VALUES ('cde'), ('efg'), ('abc'), ('bcd'), ('def'); connection master; @@ -426,13 +426,16 @@ INSERT INTO t3 VALUES ('t3_myisam1'), ('t3_myisam2'), ('t3_myisam3'); INSERT INTO t4 VALUES ('t4_myisam1'), ('t4_myisam2'), ('t4_myisam3'); --echo # Pushdown of the whole UNION +--sorted_result SELECT * from federated.t1 UNION SELECT * from federated.t2; EXPLAIN SELECT * from federated.t1 UNION SELECT * from federated.t2; --echo # Pushdown of a part of the UNION +--sorted_result SELECT * from federated.t1 UNION SELECT * from t3; EXPLAIN SELECT * from federated.t1 UNION SELECT * from t3; +--sorted_result SELECT * from federated.t1 UNION ALL SELECT * from federated.t2; EXPLAIN SELECT * from federated.t1 UNION ALL SELECT * from federated.t2; @@ -445,6 +448,7 @@ ANALYZE SELECT * from federated.t1 UNION ALL SELECT * from federated.t2; ANALYZE FORMAT=JSON SELECT * from federated.t1 UNION ALL SELECT * from federated.t2; +--sorted_result SELECT * from federated.t1 EXCEPT SELECT * from federated.t2; EXPLAIN EXTENDED SELECT * from federated.t1 EXCEPT @@ -453,6 +457,7 @@ EXPLAIN EXTENDED SELECT * from federated.t1 EXCEPT EXPLAIN FORMAT=JSON SELECT * from federated.t1 EXCEPT SELECT * from federated.t2; +--sorted_result SELECT * from federated.t1 INTERSECT SELECT * from federated.t2; EXPLAIN PARTITIONS SELECT * from federated.t1 INTERSECT @@ -462,6 +467,7 @@ EXPLAIN FORMAT=JSON SELECT * from federated.t1 INTERSECT SELECT * from federated.t2; --echo # More than two SELECTs in a UNIT: +--sorted_result SELECT * from federated.t1 INTERSECT SELECT * from federated.t2 UNION ALL SELECT * from federated.t2 EXCEPT @@ -486,6 +492,7 @@ ANALYZE SELECT count(*)+5 from federated.t1; --echo # UNION inside a derived table: the whole derived table must be pushed +--sorted_result SELECT * FROM (SELECT * FROM federated.t1 UNION ALL SELECT * FROM federated.t2) q; @@ -499,6 +506,7 @@ EXPLAIN --echo # at the server side --disable_warnings +--sorted_result SELECT count(*) FROM federated.t1 UNION SELECT count(*) FROM federated.t1 EXCEPT SELECT count(*)+1 FROM federated.t1 @@ -521,8 +529,11 @@ PREPARE stmt FROM "SELECT * from federated.t1 INTERSECT SELECT * from federated.t2 EXCEPT SELECT * from federated.t1"; +--sorted_result EXECUTE stmt; +--sorted_result EXECUTE stmt; +--sorted_result EXECUTE stmt; PREPARE stmt FROM "EXPLAIN SELECT * from federated.t1 INTERSECT @@ -530,13 +541,17 @@ PREPARE stmt FROM "EXPLAIN SELECT * from federated.t1 INTERSECT SELECT * from federated.t2 EXCEPT SELECT * from federated.t1"; +--sorted_result EXECUTE stmt; +--sorted_result EXECUTE stmt; --echo # UNIONs of mixed Federated/MyISAM tables, pushing parts of UNIONs +--sorted_result SELECT * FROM federated.t1 UNION SELECT * FROM t3; EXPLAIN SELECT * FROM federated.t1 UNION SELECT * FROM t3; +--sorted_result SELECT * FROM federated.t1 UNION ALL SELECT * FROM t3 EXCEPT SELECT * FROM federated.t2; @@ -544,6 +559,7 @@ EXPLAIN SELECT * FROM federated.t1 UNION ALL SELECT * FROM t3 EXCEPT SELECT * FROM federated.t2; +--sorted_result SELECT * FROM t3 UNION ALL SELECT * FROM federated.t1 EXCEPT SELECT * FROM t4 INTERSECT @@ -553,6 +569,7 @@ EXPLAIN SELECT * FROM t3 UNION ALL SELECT * FROM t4 INTERSECT SELECT * FROM federated.t2; +--sorted_result SELECT * FROM federated.t2 UNION ALL SELECT * FROM t3 EXCEPT SELECT * FROM t4 INTERSECT @@ -567,6 +584,7 @@ EXPLAIN (SELECT * FROM federated.t1 UNION SELECT * FROM federated.t2) UNION ALL SELECT * FROM federated.t1; +--sorted_result (SELECT * FROM federated.t1 UNION SELECT * FROM federated.t2) UNION ALL SELECT * FROM federated.t1; @@ -574,6 +592,7 @@ EXPLAIN (SELECT * FROM federated.t1 UNION EXPLAIN (SELECT * FROM federated.t1 UNION SELECT * FROM federated.t2) UNION ALL (SELECT * FROM federated.t1 UNION SELECT * FROM federated.t2); +--sorted_result (SELECT * FROM federated.t1 UNION SELECT * FROM federated.t2) UNION ALL (SELECT * FROM federated.t1 UNION SELECT * FROM federated.t2); @@ -601,17 +620,21 @@ ENGINE="FEDERATED" CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t12'; --echo # Entire UNION pushdown +--sorted_result SELECT a FROM federated.t12 UNION ALL SELECT a FROM federated.t11; EXPLAIN SELECT a FROM federated.t12 UNION ALL SELECT a FROM federated.t11; +--sorted_result SELECT a FROM federated.t11 UNION SELECT a FROM federated.t12; --echo # Partial pushdown of SELECTs composing the UNION +--sorted_result SELECT a FROM federated.t12 UNION SELECT a FROM federated.t11 UNION SELECT 123; EXPLAIN SELECT a FROM federated.t12 UNION SELECT a FROM federated.t11 UNION SELECT 123; +--sorted_result SELECT a FROM federated.t12 EXCEPT SELECT 1 UNION ALL SELECT a FROM federated.t11 EXCEPT @@ -639,9 +662,11 @@ CREATE TABLE federated.t14 (a VARCHAR(8)) ENGINE="FEDERATED" CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t14'; +--sorted_result SELECT * FROM federated.t13 UNION SELECT * FROM federated.t14; EXPLAIN SELECT * FROM federated.t13 UNION SELECT * FROM federated.t14; +--sorted_result SELECT * FROM federated.t14 UNION ALL SELECT * FROM federated.t13; SELECT * FROM federated.t14 UNION @@ -652,6 +677,7 @@ EXPLAIN SELECT * FROM federated.t14 UNION SELECT * FROM federated.t13 UNION SELECT '123456789000'; +--sorted_result SELECT * FROM federated.t13 UNION SELECT '123456789000' UNION SELECT * FROM federated.t14; @@ -671,6 +697,41 @@ SHOW CREATE TABLE t6; --sorted_result SELECT * FROM t6; +--echo # +--echo # MDEV-30828 ORDER BY clause using an integer (positional argument) +--echo # +SELECT a FROM federated.t1 UNION SELECT a FROM federated.t2 ORDER BY 1; + +SELECT a FROM federated.t1 UNION ALL SELECT a FROM federated.t2 ORDER BY a DESC; + +--echo # Check handling of incorrect ORDER BY clause +--error ER_BAD_FIELD_ERROR +SELECT a FROM federated.t1 UNION SELECT a FROM federated.t2 ORDER BY 2; +--error ER_BAD_FIELD_ERROR +PREPARE stmt FROM + "SELECT a FROM federated.t1 UNION ALL SELECT a FROM federated.t2 ORDER BY 2"; + +--error ER_BAD_FIELD_ERROR +SELECT a FROM federated.t1 UNION ALL SELECT a FROM federated.t2 ORDER BY 2,1,3; +--error ER_TABLENAME_NOT_ALLOWED_HERE +SELECT a FROM federated.t1 UNION ALL SELECT a FROM federated.t2 ORDER BY t1.a; +SELECT * from federated.t1 INTERSECT + SELECT * from federated.t2 UNION ALL + SELECT * from federated.t2 EXCEPT + SELECT * from federated.t1 + ORDER BY 1; +--error ER_BAD_FIELD_ERROR +SELECT * from federated.t1 INTERSECT + SELECT * from federated.t2 UNION ALL + SELECT * from federated.t2 EXCEPT + SELECT * from federated.t1 + ORDER BY 3; +--echo # UNION of mixed Federated/MyISAM tables, pushing parts of UNIONs +SELECT * FROM federated.t1 UNION SELECT * FROM t3 ORDER BY a; +--error ER_BAD_FIELD_ERROR +SELECT * FROM federated.t1 UNION SELECT * FROM t3 ORDER BY 2; + + # Cleanup connection master; DROP TABLES federated.t1, federated.t2, t3, t4, t5, t6, federated.t11, diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 641b1b56899..5e6108bda54 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1057,6 +1057,8 @@ private: bool exec_inner(); bool is_derived_eliminated() const; bool set_direct_union_result(select_result *sel_result); + bool prepare_pushdown(bool use_direct_union_result, + select_result *sel_result); }; typedef class st_select_lex_unit SELECT_LEX_UNIT; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a158ca7763c..a27d2185587 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -563,6 +563,7 @@ void JOIN::init(THD *thd_arg, List &fields_arg, sjm_scan_tables= 0; is_orig_degenerated= false; with_ties_order_count= 0; + prepared= false; }; @@ -1816,6 +1817,7 @@ JOIN::prepare(TABLE_LIST *tables_init, COND *conds_init, uint og_num, unit= unit_arg; if (prepare_stage2()) goto err; + prepared= true; DBUG_RETURN(0); // All OK @@ -5185,7 +5187,8 @@ mysql_select(THD *thd, TABLE_LIST *tables, List &fields, COND *conds, } else { - if ((err= join->prepare(tables, conds, og_num, order, false, group, + if (!join->prepared && + (err= join->prepare(tables, conds, og_num, order, false, group, having, proc_param, select_lex, unit))) { goto err; @@ -5211,7 +5214,8 @@ mysql_select(THD *thd, TABLE_LIST *tables, List &fields, COND *conds, DBUG_RETURN(TRUE); THD_STAGE_INFO(thd, stage_init); thd->lex->used_tables=0; - if ((err= join->prepare(tables, conds, og_num, order, false, group, having, + if (!join->prepared && + (err= join->prepare(tables, conds, og_num, order, false, group, having, proc_param, select_lex, unit))) { goto err; diff --git a/sql/sql_select.h b/sql/sql_select.h index d2072cbedef..fbad610f6e5 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1596,6 +1596,8 @@ public: */ bool impossible_where; + bool prepared; + /* All fields used in the query processing. diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 4041e4b25e8..44bdabe18cb 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1759,24 +1759,6 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg, goto err; cont: - pushdown_unit= find_unit_handler(thd, this); - if (pushdown_unit) - { - if (unlikely(pushdown_unit->prepare())) - goto err; - /* - Always use select_union_direct result for pushed down units, overwrite - the previous union_result unless select_union_direct is already used - */ - if (!use_direct_union_result) - { - if (unlikely(set_direct_union_result(sel_result))) - goto err; - fake_select_lex= NULL; - instantiate_tmp_table= false; - use_direct_union_result= true; - } - } /* If the query is using select_union_direct, we have postponed preparation of the underlying select_result until column types @@ -1919,37 +1901,6 @@ cont: if (unlikely(saved_error)) goto err; - - if (fake_select_lex != NULL && - (thd->stmt_arena->is_stmt_prepare() || - (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW))) - { - /* Validate the global parameters of this union */ - - init_prepare_fake_select_lex(thd, TRUE); - /* Should be done only once (the only item_list per statement) */ - DBUG_ASSERT(fake_select_lex->join == 0); - if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->variables.option_bits, - result))) - { - fake_select_lex->table_list.empty(); - DBUG_RETURN(TRUE); - } - - /* - Fake st_select_lex should have item list for correct ref_array - allocation. - */ - fake_select_lex->item_list= item_list; - - thd->lex->current_select= fake_select_lex; - - /* - We need to add up n_sum_items in order to make the correct - allocation in setup_ref_array(). - */ - fake_select_lex->n_child_sum_items+= global_parameters()->n_sum_items; - } } else { @@ -1959,23 +1910,45 @@ cont: */ table->reset_item_list(&item_list, hidden); } - if (fake_select_lex != NULL && - (thd->stmt_arena->is_stmt_prepare() || - (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW))) + + if (fake_select_lex != NULL) { - if (!fake_select_lex->join && - !(fake_select_lex->join= - new JOIN(thd, item_list, thd->variables.option_bits, result))) + init_prepare_fake_select_lex(thd, TRUE); + + DBUG_ASSERT(fake_select_lex->join == 0); + if (!(fake_select_lex->join= new JOIN(thd, item_list, options, result))) { - fake_select_lex->table_list.empty(); - DBUG_RETURN(TRUE); + fake_select_lex->table_list.empty(); + DBUG_RETURN(TRUE); } - saved_error= fake_select_lex->join-> - prepare(fake_select_lex->table_list.first, 0, + + /* + Fake st_select_lex should have item list for correct ref_array + allocation. + */ + fake_select_lex->item_list= item_list; + + thd->lex->current_select= fake_select_lex; + + /* + We need to add up n_sum_items in order to make the correct + allocation in setup_ref_array(). + */ + fake_select_lex->n_child_sum_items+= global_parameters()->n_sum_items; + fake_select_lex->join->no_const_tables= TRUE; + saved_error= fake_select_lex->join->prepare( + fake_select_lex->table_list.first, 0, global_parameters()->order_list.elements, // og_num global_parameters()->order_list.first, // order false, NULL, NULL, NULL, fake_select_lex, this); - fake_select_lex->table_list.empty(); + } + + if (!thd->lex->is_view_context_analysis()) + pushdown_unit= find_unit_handler(thd, this); + if (pushdown_unit) + { + if (prepare_pushdown(use_direct_union_result, sel_result)) + goto err; } } @@ -1989,6 +1962,36 @@ err: DBUG_RETURN(TRUE); } +/** + @brief + Prepare st_select_lex_unit for the pushdown handler processing + @details + Creates and initializes data structures required for processing of the + pushdown handler. Validates fake_select_lex then discards it and sets + direct union result which is necessary for pushed down statements + @return + false - success + true - failure +*/ +bool st_select_lex_unit::prepare_pushdown(bool use_direct_union_result, + select_result *sel_result) +{ + if (unlikely(pushdown_unit->prepare())) + return true; + + if(!use_direct_union_result) + { + /* + Always use select_union_direct result for pushed down units, overwrite + the previous union_result unless select_union_direct is already used + */ + if (unlikely(set_direct_union_result(sel_result))) + return true; + } + return false; +} + + bool st_select_lex_unit::set_direct_union_result(select_result *sel_result) { SELECT_LEX *last= first_select(); @@ -2466,45 +2469,13 @@ bool st_select_lex_unit::exec_inner() saved_error= true; set_limit(global_parameters()); - init_prepare_fake_select_lex(thd, first_execution); JOIN *join= fake_select_lex->join; saved_error= false; - if (!join) + if (!(thd->stmt_arena->is_stmt_prepare() || + (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW)) && + first_execution) { - /* - allocate JOIN for fake select only once (prevent - mysql_select automatic allocation) - TODO: The above is nonsense. mysql_select() will not allocate the - join if one already exists. There must be some other reason why we - don't let it allocate the join. Perhaps this is because we need - some special parameter values passed to join constructor? - */ - if (unlikely(!(fake_select_lex->join= - new JOIN(thd, item_list, fake_select_lex->options, - result)))) - { - fake_select_lex->table_list.empty(); - goto err; - } - fake_select_lex->join->no_const_tables= TRUE; - - /* - Fake st_select_lex should have item list for correct ref_array - allocation. - */ - fake_select_lex->item_list= item_list; - - /* - We need to add up n_sum_items in order to make the correct - allocation in setup_ref_array(). - Don't add more sum_items if we have already done JOIN::prepare - for this (with a different join object) - */ - if (fake_select_lex->ref_pointer_array.is_null()) - fake_select_lex->n_child_sum_items+= global_parameters()->n_sum_items; - - if (!was_executed) - save_union_explain_part2(thd->lex->explain); + save_union_explain_part2(thd->lex->explain); saved_error= mysql_select(thd, &result_table_list, item_list, NULL, @@ -2527,7 +2498,6 @@ bool st_select_lex_unit::exec_inner() subquery execution rather than EXPLAIN line production. In order to reset them back, we re-do all of the actions (yes it is ugly): */ // psergey-todo: is the above really necessary anymore?? - join->init(thd, item_list, fake_select_lex->options, result); saved_error= mysql_select(thd, &result_table_list, item_list, NULL, global_parameters()->order_list.elements, global_parameters()->order_list.first, @@ -2557,7 +2527,6 @@ bool st_select_lex_unit::exec_inner() } } thd->lex->current_select= lex_select_save; -err: thd->lex->set_limit_rows_examined(); return saved_error; } @@ -2822,12 +2791,9 @@ bool st_select_lex_unit::change_result(select_result_interceptor *new_result, if (sl->join->change_result(new_result, old_result)) return true; /* purecov: inspected */ } - /* - If there were a fake_select_lex->join, we would have to change the - result of that also, but change_result() is called before such an - object is created. - */ - DBUG_ASSERT(fake_select_lex == NULL || fake_select_lex->join == NULL); + + if (fake_select_lex && fake_select_lex->join) + fake_select_lex->join->change_result(new_result, old_result); return false; }