diff options
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r-- | sql/sql_select.cc | 211 |
1 files changed, 99 insertions, 112 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4ce29f1d666..3134f8eb007 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -53,6 +53,7 @@ #include "log_slow.h" #include "sql_derived.h" #include "sql_statistics.h" +#include "sql_cte.h" #include "debug_sync.h" // DEBUG_SYNC #include <m_ctype.h> @@ -448,7 +449,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, this field from inner subqueries. @return Status - @retval true An error occured. + @retval true An error occurred. @retval false OK. */ @@ -828,6 +829,10 @@ JOIN::prepare(Item ***rref_pointer_array, DBUG_RETURN(-1); /* purecov: inspected */ thd->lex->allow_sum_func= save_allow_sum_func; } + + With_clause *with_clause=select_lex->get_with_clause(); + if (with_clause && with_clause->prepare_unreferenced_elements(thd)) + DBUG_RETURN(1); int res= check_and_do_in_subquery_rewrites(this); @@ -1430,7 +1435,7 @@ JOIN::optimize_inner() } select= make_select(*table, const_table_map, - const_table_map, conds, 1, &error); + const_table_map, conds, (SORT_INFO*) 0, 1, &error); if (error) { /* purecov: inspected */ error= -1; /* purecov: inspected */ @@ -2368,15 +2373,11 @@ JOIN::reinit() { exec_tmp_table1->file->extra(HA_EXTRA_RESET_STATE); exec_tmp_table1->file->ha_delete_all_rows(); - free_io_cache(exec_tmp_table1); - filesort_free_buffers(exec_tmp_table1,0); } if (exec_tmp_table2) { exec_tmp_table2->file->extra(HA_EXTRA_RESET_STATE); exec_tmp_table2->file->ha_delete_all_rows(); - free_io_cache(exec_tmp_table2); - filesort_free_buffers(exec_tmp_table2,0); } clear_sj_tmp_tables(this); if (items0) @@ -3193,12 +3194,12 @@ void JOIN::exec_inner() DBUG_VOID_RETURN; sortorder= curr_join->sortorder; if (curr_join->const_tables != curr_join->table_count && - !curr_join->join_tab[curr_join->const_tables].table->sort.io_cache) + !curr_join->join_tab[curr_join->const_tables].filesort) { /* - If no IO cache exists for the first table then we are using an - INDEX SCAN and no filesort. Thus we should not remove the sorted - attribute on the INDEX SCAN. + If no filesort for the first table then we are using an + INDEX SCAN. Thus we should not remove the sorted attribute + on the INDEX SCAN. */ skip_sort_order= 1; } @@ -4095,6 +4096,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list, select= make_select(s->table, found_const_table_map, found_const_table_map, *s->on_expr_ref ? *s->on_expr_ref : join->conds, + (SORT_INFO*) 0, 1, &error); if (!select) goto error; @@ -9043,13 +9045,21 @@ JOIN::make_simple_join(JOIN *parent, TABLE *temp_table) /* Reuse TABLE * and JOIN_TAB if already allocated by a previous call to this function through JOIN::exec (may happen for sub-queries). + + psergey-todo: here, save the pointer for original join_tabs. */ - if (!parent->join_tab_reexec && - !(parent->join_tab_reexec= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)))) - DBUG_RETURN(TRUE); /* purecov: inspected */ + if (!(join_tab= parent->join_tab_reexec)) + { + if (!(join_tab= parent->join_tab_reexec= + (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)))) + DBUG_RETURN(TRUE); /* purecov: inspected */ + } + else + { + /* Free memory used by previous allocations */ + delete join_tab->filesort; + } - // psergey-todo: here, save the pointer for original join_tabs. - join_tab= parent->join_tab_reexec; table= &parent->table_reexec[0]; parent->table_reexec[0]= temp_table; table_count= top_join_tab_count= 1; @@ -11412,13 +11422,16 @@ bool error_if_full_join(JOIN *join) void JOIN_TAB::cleanup() { DBUG_ENTER("JOIN_TAB::cleanup"); - DBUG_PRINT("enter", ("table %s.%s", + DBUG_PRINT("enter", ("tab: %p table %s.%s", + this, (table ? table->s->db.str : "?"), (table ? table->s->table_name.str : "?"))); delete select; select= 0; delete quick; quick= 0; + delete filesort; + filesort= 0; if (cache) { cache->free(); @@ -11817,8 +11830,8 @@ void JOIN::cleanup(bool full) JOIN_TAB *first_tab= first_top_level_tab(this, WITHOUT_CONST_TABLES); if (first_tab->table) { - free_io_cache(first_tab->table); - filesort_free_buffers(first_tab->table, full); + delete first_tab->filesort; + first_tab->filesort= 0; } } if (full) @@ -12853,7 +12866,7 @@ bool Item_func_eq::check_equality(THD *thd, COND_EQUAL *cond_equal, equality predicates that is equivalent to the conjunction. Thus, =(a1,a2,a3) can substitute for ((a1=a3) AND (a2=a3) AND (a2=a1)) as it is equivalent to ((a1=a2) AND (a2=a3)). - The function always makes a substitution of all equality predicates occured + The function always makes a substitution of all equality predicates occurred in a conjuction for a minimal set of multiple equality predicates. This set can be considered as a canonical representation of the sub-conjunction of the equality predicates. @@ -15628,8 +15641,6 @@ const_expression_in_where(COND *cond, Item *comp_item, Field *comp_field, the record in the original table. If item == NULL then fill_record() will update the temporary table - @param convert_blob_length If >0 create a varstring(convert_blob_length) - field instead of blob. @retval NULL on error @@ -15639,23 +15650,12 @@ const_expression_in_where(COND *cond, Item *comp_item, Field *comp_field, Field *create_tmp_field_from_field(THD *thd, Field *org_field, const char *name, TABLE *table, - Item_field *item, uint convert_blob_length) + Item_field *item) { Field *new_field; - /* - Make sure that the blob fits into a Field_varstring which has - 2-byte lenght. - */ - if (convert_blob_length && convert_blob_length <= Field_varstring::MAX_SIZE && - (org_field->flags & BLOB_FLAG)) - new_field= new Field_varstring(convert_blob_length, - org_field->maybe_null(), - org_field->field_name, table->s, - org_field->charset()); - else - new_field= org_field->make_new_field(thd->mem_root, table, - table == org_field->table); + new_field= org_field->make_new_field(thd->mem_root, table, + table == org_field->table); if (new_field) { new_field->init(table); @@ -15682,9 +15682,7 @@ Field *create_tmp_field_from_field(THD *thd, Field *org_field, } -Field *Item::create_tmp_field(bool group, TABLE *table, - uint convert_blob_length, - uint convert_int_length) +Field *Item::create_tmp_field(bool group, TABLE *table, uint convert_int_length) { Field *UNINIT_VAR(new_field); MEM_ROOT *mem_root= table->in_use->mem_root; @@ -15718,16 +15716,6 @@ Field *Item::create_tmp_field(bool group, TABLE *table, */ if (field_type() == MYSQL_TYPE_GEOMETRY) new_field= tmp_table_field_from_field_type(table, true, false); - /* - Make sure that the blob fits into a Field_varstring which has - 2-byte lenght. - */ - else if (max_length / collation.collation->mbmaxlen > 255 && - convert_blob_length <= Field_varstring::MAX_SIZE && - convert_blob_length) - new_field= new (mem_root) - Field_varstring(convert_blob_length, maybe_null, - name, table->s, collation.collation); else new_field= make_string_field(table); new_field->set_derivation(collation.derivation); @@ -15773,12 +15761,11 @@ Field *Item::create_tmp_field(bool group, TABLE *table, */ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, - Item ***copy_func, bool modify_item, - uint convert_blob_length) + Item ***copy_func, bool modify_item) { Field *UNINIT_VAR(new_field); DBUG_ASSERT(thd == table->in_use); - new_field= item->Item::create_tmp_field(false, table, convert_blob_length); + new_field= item->Item::create_tmp_field(false, table); if (copy_func && item->real_item()->is_result_field()) *((*copy_func)++) = item; // Save for copy_funcs @@ -15841,8 +15828,6 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table) the record in the original table. If modify_item is 0 then fill_record() will update the temporary table - @param convert_blob_length If >0 create a varstring(convert_blob_length) - field instead of blob. @retval 0 on error @@ -15855,8 +15840,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Field **default_field, bool group, bool modify_item, bool table_cant_handle_bit_fields, - bool make_copy_field, - uint convert_blob_length) + bool make_copy_field) { Field *result; Item::Type orig_type= type; @@ -15873,7 +15857,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, switch (type) { case Item::SUM_FUNC_ITEM: { - result= item->create_tmp_field(group, table, convert_blob_length); + result= item->create_tmp_field(group, table); if (!result) my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); return result; @@ -15909,7 +15893,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, item->maybe_null= orig_item->maybe_null; } result= create_tmp_field_from_item(thd, item, table, NULL, - modify_item, convert_blob_length); + modify_item); *from_field= field->field; if (result && modify_item) field->result_field= result; @@ -15921,7 +15905,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, { *from_field= field->field; result= create_tmp_field_from_item(thd, item, table, copy_func, - modify_item, convert_blob_length); + modify_item); if (result && modify_item) field->result_field= result; } @@ -15931,8 +15915,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, item->name, table, modify_item ? field : - NULL, - convert_blob_length); + NULL); if (orig_type == Item::REF_ITEM && orig_modify) ((Item_ref*)orig_item)->set_result_field(result); /* @@ -15966,8 +15949,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, sp_result_field, item_func_sp->name, table, - NULL, - convert_blob_length); + NULL); if (modify_item) item->set_result_field(result_field); @@ -15999,7 +15981,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, } return create_tmp_field_from_item(thd, item, table, (make_copy_field ? 0 : copy_func), - modify_item, convert_blob_length); + modify_item); case Item::TYPE_HOLDER: result= ((Item_type_holder *)item)->make_field_by_type(table); result->set_derivation(item->collation.derivation); @@ -16309,8 +16291,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, create_tmp_field(thd, table, arg, arg->type(), ©_func, tmp_from_field, &default_field[fieldnr], group != 0,not_all_columns, - distinct, 0, - param->convert_blob_length); + distinct, false); if (!new_field) goto err; // Should be OOM tmp_from_field++; @@ -16380,8 +16361,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, to be usable in this case too. */ item->marker == 4 || param->bit_fields_as_long, - force_copy_fields, - param->convert_blob_length); + force_copy_fields); if (!new_field) { @@ -16745,8 +16725,6 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, cur_group->buff++; // Pointer to field data group_buff++; // Skipp null flag } - /* In GROUP BY 'a' and 'a ' are equal for VARCHAR fields */ - key_part_info->key_part_flag|= HA_END_SPACE_ARE_EQUAL; group_buff+= cur_group->field->pack_length(); } keyinfo->key_length+= key_part_info->length; @@ -17593,7 +17571,6 @@ free_tmp_table(THD *thd, TABLE *entry) /* free blobs */ for (Field **ptr=entry->field ; *ptr ; ptr++) (*ptr)->free(); - free_io_cache(entry); if (entry->temp_pool_slot != MY_BIT_NONE) bitmap_lock_clear_bit(&temp_pool, entry->temp_pool_slot); @@ -19056,7 +19033,7 @@ int join_init_read_record(JOIN_TAB *tab) if (!tab->preread_init_done && tab->preread_init()) return 1; if (init_read_record(&tab->read_record, tab->join->thd, tab->table, - tab->select,1,1, FALSE)) + tab->select, tab->filesort, 1,1, FALSE)) return 1; return (*tab->read_record.read_record)(&tab->read_record); } @@ -19074,7 +19051,7 @@ join_read_record_no_init(JOIN_TAB *tab) save_copy_end= tab->read_record.copy_field_end; init_read_record(&tab->read_record, tab->join->thd, tab->table, - tab->select,1,1, FALSE); + tab->select, tab->filesort, 1, 1, FALSE); tab->read_record.copy_field= save_copy; tab->read_record.copy_field_end= save_copy_end; @@ -19319,11 +19296,9 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), TABLE *table=jt->table; join->select_options ^= OPTION_FOUND_ROWS; - if (table->sort.record_pointers || - (table->sort.io_cache && my_b_inited(table->sort.io_cache))) + if (jt->filesort) // If filesort was used { - /* Using filesort */ - join->send_records= table->sort.found_records; + join->send_records= jt->filesort->found_rows; } else { @@ -21053,8 +21028,7 @@ use_filesort: 'join' is modified to use this index. - If no index, create with filesort() an index file that can be used to retrieve rows in order (should be done with 'read_record'). - The sorted data is stored in tab->table and will be freed when calling - free_io_cache(tab->table). + The sorted data is stored in tab->filesort RETURN VALUES 0 ok @@ -21067,15 +21041,12 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, ha_rows filesort_limit, ha_rows select_limit, bool is_order_by) { - uint length= 0; - ha_rows examined_rows; - ha_rows found_rows; - ha_rows filesort_retval= HA_POS_ERROR; + uint length; TABLE *table; SQL_SELECT *select; JOIN_TAB *tab; - int err= 0; bool quick_created= FALSE; + SORT_INFO *file_sort= 0; DBUG_ENTER("create_sort_index"); if (join->table_count == join->const_tables) @@ -21160,15 +21131,19 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, } tab->update_explain_data(join->const_tables); + /* + Calculate length of join->order as this may be longer than 'order', + which may come from 'group by'. This is needed as join->sortorder is + used both for grouping and ordering. + */ + length= 0; for (ORDER *ord= join->order; ord; ord= ord->next) length++; - if (!(join->sortorder= + + if (!(join->sortorder= make_unireg_sortorder(thd, order, &length, join->sortorder))) goto err; /* purecov: inspected */ - table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), - MYF(MY_WME | MY_ZEROFILL| - MY_THREAD_SPECIFIC)); table->status=0; // May be wrong if quick_select if (!tab->preread_init_done && tab->preread_init()) @@ -21212,12 +21187,18 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, if (table->s->tmp_table) table->file->info(HA_STATUS_VARIABLE); // Get record count - filesort_retval= filesort(thd, table, join->sortorder, length, - select, filesort_limit, 0, - &examined_rows, &found_rows, - join->explain->ops_tracker.report_sorting(thd)); - table->sort.found_records= filesort_retval; - tab->records= join->select_options & OPTION_FOUND_ROWS ? found_rows : filesort_retval; + file_sort= filesort(thd, table, join->sortorder, length, + select, filesort_limit, 0, + join->explain->ops_tracker.report_sorting(thd)); + DBUG_ASSERT(tab->filesort == 0); + tab->filesort= file_sort; + tab->records= 0; + if (file_sort) + { + tab->records= join->select_options & OPTION_FOUND_ROWS ? + file_sort->found_rows : file_sort->return_rows; + tab->join->join_examined_rows+= file_sort->examined_rows; + } if (quick_created) { @@ -21240,12 +21221,8 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, tab->type=JT_ALL; // Read with normal read_record tab->read_first_record= join_init_read_record; tab->table->file->ha_index_or_rnd_end(); - - if (err) - goto err; - tab->join->join_examined_rows+= examined_rows; - DBUG_RETURN(filesort_retval == HA_POS_ERROR); + DBUG_RETURN(file_sort == 0); err: DBUG_RETURN(-1); } @@ -21368,7 +21345,6 @@ remove_duplicates(JOIN *join, TABLE *table, List<Item> &fields, Item *having) if (thd->killed == ABORT_QUERY) thd->reset_killed(); - free_io_cache(table); // Safety table->file->info(HA_STATUS_VARIABLE); if (table->s->db_type() == heap_hton || (!table->s->blob_fields && @@ -21764,7 +21740,11 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, */ if (order_item->type() == Item::INT_ITEM && order_item->basic_const_item()) { /* Order by position */ - uint count= (uint) order_item->val_int(); + uint count; + if (order->counter_used) + count= order->counter; // counter was once resolved + else + count= (uint) order_item->val_int(); if (!count || count > fields.elements) { my_error(ER_BAD_FIELD_ERROR, MYF(0), @@ -21781,7 +21761,7 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, select_item= find_item_in_list(order_item, fields, &counter, REPORT_EXCEPT_NOT_FOUND, &resolution); if (!select_item) - return TRUE; /* The item is not unique, or some other error occured. */ + return TRUE; /* The item is not unique, or some other error occurred. */ /* Check whether the resolved field is not ambiguos. */ @@ -23131,8 +23111,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) } join_tab->set_select_cond(cond, __LINE__); } - else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0, - &error))) + else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, + (SORT_INFO*) 0, 0, &error))) join_tab->set_select_cond(cond, __LINE__); DBUG_RETURN(error ? TRUE : FALSE); @@ -24192,9 +24172,8 @@ int JOIN::save_explain_data_intern(Explain_query *output, bool need_tmp_table, /* There should be no attempts to save query plans for merged selects */ DBUG_ASSERT(!join->select_lex->master_unit()->derived || - join->select_lex->master_unit()->derived->is_materialized_derived()); - - explain= NULL; + join->select_lex->master_unit()->derived->is_materialized_derived() || + join->select_lex->master_unit()->derived->is_with_table()); /* Don't log this into the slow query log */ @@ -24704,11 +24683,19 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str, } else if (derived) { - // A derived table - str->append('('); - derived->print(str, query_type); - str->append(')'); - cmp_name= ""; // Force printing of alias + if (!derived->derived->is_with_table()) + { + // A derived table + str->append('('); + derived->print(str, query_type); + str->append(')'); + cmp_name= ""; // Force printing of alias + } + else + { + append_identifier(thd, str, table_name, table_name_length); + cmp_name= table_name; + } } else { @@ -25104,7 +25091,7 @@ void JOIN::restore_query_plan(Join_plan_state *restore_from) @retval REOPT_NEW_PLAN there is a new plan. @retval REOPT_OLD_PLAN no new improved plan was produced, use the old one. - @retval REOPT_ERROR an irrecovarable error occured during reoptimization. + @retval REOPT_ERROR an irrecovarable error occurred during reoptimization. */ JOIN::enum_reopt_result |