sql_select.cc 408 KB
Newer Older
unknown's avatar
af  
unknown committed
1
/* Copyright (C) 2000-2004 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
unknown's avatar
unknown committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


/* mysql_select and join optimization */

#ifdef __GNUC__
#pragma implementation				// gcc: Class implementation
#endif

#include "mysql_priv.h"
#include "sql_select.h"
unknown's avatar
unknown committed
26

unknown's avatar
unknown committed
27 28 29 30 31
#include <m_ctype.h>
#include <hash.h>
#include <ft_global.h>

const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
32
			      "MAYBE_REF","ALL","range","index","fulltext",
33
			      "ref_or_null","unique_subquery","index_subquery",
unknown's avatar
unknown committed
34
                              "index_merge"
35
};
unknown's avatar
unknown committed
36

37 38 39
const key_map key_map_empty(0);
const key_map key_map_full(~0);

40
static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
41
static bool make_join_statistics(JOIN *join, TABLE_LIST *leaves, COND *conds,
unknown's avatar
unknown committed
42
				 DYNAMIC_ARRAY *keyuse);
43 44
static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
				JOIN_TAB *join_tab,
45
                                uint tables, COND *conds,
unknown's avatar
unknown committed
46
                                COND_EQUAL *cond_equal,
47
				table_map table_map, SELECT_LEX *select_lex);
unknown's avatar
unknown committed
48 49
static int sort_keyuse(KEYUSE *a,KEYUSE *b);
static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key);
50 51
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
			       table_map used_tables);
unknown's avatar
af  
unknown committed
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
static void choose_plan(JOIN *join,table_map join_tables);

static void best_access_path(JOIN *join, JOIN_TAB *s, THD *thd,
                             table_map remaining_tables, uint idx,
                             double record_count, double read_time);
static void optimize_straight_join(JOIN *join, table_map join_tables);
static void greedy_search(JOIN *join, table_map remaining_tables,
                             uint depth, uint prune_level);
static void best_extension_by_limited_search(JOIN *join,
                                             table_map remaining_tables,
                                             uint idx, double record_count,
                                             double read_time, uint depth,
                                             uint prune_level);
static uint determine_search_depth(JOIN* join);
static int join_tab_cmp(const void* ptr1, const void* ptr2);
67
static int join_tab_cmp_straight(const void* ptr1, const void* ptr2);
unknown's avatar
af  
unknown committed
68 69 70 71
/*
  TODO: 'find_best' is here only temporarily until 'greedy_search' is
  tested and approved.
*/
unknown's avatar
unknown committed
72 73 74 75 76
static void find_best(JOIN *join,table_map rest_tables,uint index,
		      double record_count,double read_time);
static uint cache_record_length(JOIN *join,uint index);
static double prev_record_reads(JOIN *join,table_map found_ref);
static bool get_best_combination(JOIN *join);
unknown's avatar
unknown committed
77 78
static store_key *get_store_key(THD *thd,
				KEYUSE *keyuse, table_map used_tables,
unknown's avatar
unknown committed
79 80 81
				KEY_PART_INFO *key_part, char *key_buff,
				uint maybe_null);
static bool make_simple_join(JOIN *join,TABLE *tmp_table);
82
static void make_outerjoin_info(JOIN *join);
unknown's avatar
unknown committed
83 84
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
static void make_join_readinfo(JOIN *join,uint options);
85
static bool only_eq_ref_tables(JOIN *join, ORDER *order, table_map tables);
unknown's avatar
unknown committed
86 87 88 89
static void update_depend_map(JOIN *join);
static void update_depend_map(JOIN *join, ORDER *order);
static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond,
			   bool *simple_order);
90
static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
unknown's avatar
unknown committed
91 92
			    List<Item> &fields, bool send_row,
			    uint select_options, const char *info,
93 94
			    Item *having, Procedure *proc,
			    SELECT_LEX_UNIT *unit);
unknown's avatar
unknown committed
95
static COND *build_equal_items(THD *thd, COND *cond,
unknown's avatar
unknown committed
96 97 98
                               COND_EQUAL *inherited,
                               List<TABLE_LIST> *join_list,
                               COND_EQUAL **cond_equal_ref);
99
static COND* substitute_for_best_equal_field(COND *cond,
unknown's avatar
unknown committed
100
                                             COND_EQUAL *cond_equal,
101
                                             void *table_join_idx);
102 103
static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list,
                            COND *conds, bool top);
unknown's avatar
unknown committed
104
static COND *optimize_cond(JOIN *join, COND *conds,
unknown's avatar
unknown committed
105
                           List<TABLE_LIST> *join_list,
unknown's avatar
af  
unknown committed
106
			   Item::cond_result *cond_value);
107
static bool resolve_nested_join (TABLE_LIST *table);
unknown's avatar
af  
unknown committed
108 109
static COND *remove_eq_conds(THD *thd, COND *cond, 
			     Item::cond_result *cond_value);
unknown's avatar
unknown committed
110 111 112
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
static bool open_tmp_table(TABLE *table);
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
113
				    ulong options);
114
static Next_select_func setup_end_select_func(JOIN *join);
unknown's avatar
unknown committed
115 116 117 118
static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table,
		     Procedure *proc);
static int sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
static int sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
unknown's avatar
af  
unknown committed
119
static int flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last);
unknown's avatar
unknown committed
120 121 122 123 124 125 126 127 128
static int end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
static int end_send_group(JOIN *join, JOIN_TAB *join_tab,bool end_of_records);
static int end_write(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
static int end_update(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
static int end_unique_update(JOIN *join,JOIN_TAB *join_tab,
			     bool end_of_records);
static int end_write_group(JOIN *join, JOIN_TAB *join_tab,
			   bool end_of_records);
static int test_if_group_changed(List<Item_buff> &list);
129
static int join_read_const_table(JOIN_TAB *tab, POSITION *pos);
unknown's avatar
unknown committed
130 131 132 133
static int join_read_system(JOIN_TAB *tab);
static int join_read_const(JOIN_TAB *tab);
static int join_read_key(JOIN_TAB *tab);
static int join_read_always_key(JOIN_TAB *tab);
134
static int join_read_last_key(JOIN_TAB *tab);
unknown's avatar
unknown committed
135 136 137 138 139
static int join_no_more_records(READ_RECORD *info);
static int join_read_next(READ_RECORD *info);
static int join_init_quick_read_record(JOIN_TAB *tab);
static int test_if_quick_select(JOIN_TAB *tab);
static int join_init_read_record(JOIN_TAB *tab);
140 141 142 143 144 145
static int join_read_first(JOIN_TAB *tab);
static int join_read_next(READ_RECORD *info);
static int join_read_next_same(READ_RECORD *info);
static int join_read_last(JOIN_TAB *tab);
static int join_read_prev_same(READ_RECORD *info);
static int join_read_prev(READ_RECORD *info);
unknown's avatar
unknown committed
146 147
static int join_ft_read_first(JOIN_TAB *tab);
static int join_ft_read_next(READ_RECORD *info);
148 149
static int join_read_always_key_or_null(JOIN_TAB *tab);
static int join_read_next_same_or_null(READ_RECORD *info);
unknown's avatar
unknown committed
150 151 152
static COND *make_cond_for_table(COND *cond,table_map table,
				 table_map used_table);
static Item* part_of_refkey(TABLE *form,Field *field);
153
uint find_shortest_key(TABLE *table, const key_map *usable_keys);
unknown's avatar
unknown committed
154
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
155
				    ha_rows select_limit, bool no_changes);
156
static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
unknown's avatar
unknown committed
157
			     ha_rows filesort_limit, ha_rows select_limit);
158 159
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
			     Item *having);
unknown's avatar
unknown committed
160
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
161
				   ulong offset,Item *having);
unknown's avatar
unknown committed
162
static int remove_dup_with_hash_index(THD *thd,TABLE *table,
unknown's avatar
unknown committed
163
				      uint field_count, Field **first_field,
164

165
				      ulong key_length,Item *having);
unknown's avatar
unknown committed
166 167 168
static int join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count);
static ulong used_blob_length(CACHE_FIELD **ptr);
static bool store_record_in_cache(JOIN_CACHE *cache);
169 170
static void reset_cache_read(JOIN_CACHE *cache);
static void reset_cache_write(JOIN_CACHE *cache);
unknown's avatar
unknown committed
171 172 173 174
static void read_cached_record(JOIN_TAB *tab);
static bool cmp_buffer_with_ref(JOIN_TAB *tab);
static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
			     List<Item> &all_fields,ORDER *new_order);
175 176 177
static ORDER *create_distinct_group(THD *thd, ORDER *order,
				    List<Item> &fields,
				    bool *all_order_by_fields_used);
unknown's avatar
unknown committed
178 179 180
static bool test_if_subpart(ORDER *a,ORDER *b);
static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables);
static void calc_group_buffer(JOIN *join,ORDER *group);
181
static bool make_group_fields(JOIN *main_join, JOIN *curr_join);
unknown's avatar
unknown committed
182
static bool alloc_group_fields(JOIN *join,ORDER *group);
183
// Create list for using with tempory table
184
static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
185 186 187 188 189 190 191 192
				     List<Item> &new_list1,
				     List<Item> &new_list2,
				     uint elements, List<Item> &items);
// Create list for using with tempory table
static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
				      List<Item> &new_list1,
				      List<Item> &new_list2,
				      uint elements, List<Item> &items);
unknown's avatar
unknown committed
193 194
static void init_tmptable_sum_functions(Item_sum **func);
static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
unknown's avatar
unknown committed
195
static void copy_sum_funcs(Item_sum **func_ptr, Item_sum **end);
unknown's avatar
unknown committed
196
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
197
static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr);
198
static bool init_sum_functions(Item_sum **func, Item_sum **end);
unknown's avatar
unknown committed
199
static bool update_sum_func(Item_sum **func);
200
static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
unknown's avatar
unknown committed
201
			    bool distinct, const char *message=NullS);
202
static Item *remove_additional_cond(Item* conds);
203
static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab);
unknown's avatar
unknown committed
204

205

206 207 208 209
/*
  This handles SELECT with and without UNION
*/

210 211
bool handle_select(THD *thd, LEX *lex, select_result *result,
                   ulong setup_tables_done_option)
212
{
unknown's avatar
unknown committed
213
  bool res;
214
  register SELECT_LEX *select_lex = &lex->select_lex;
215 216
  DBUG_ENTER("handle_select");

unknown's avatar
unknown committed
217
  if (select_lex->next_select())
218
    res= mysql_union(thd, lex, result, &lex->unit, setup_tables_done_option);
219
  else
unknown's avatar
af  
unknown committed
220 221 222
  {
    SELECT_LEX_UNIT *unit= &lex->unit;
    unit->set_limit(unit->global_parameters, select_lex);
223 224 225 226 227
    /*
      'options' of mysql_select will be set in JOIN, as far as JOIN for
      every PS/SP execution new, we will not need reset this flag if 
      setup_tables_done_option changed for next rexecution
    */
228 229 230 231 232 233 234 235 236 237
    res= mysql_select(thd, &select_lex->ref_pointer_array,
		      (TABLE_LIST*) select_lex->table_list.first,
		      select_lex->with_wild, select_lex->item_list,
		      select_lex->where,
		      select_lex->order_list.elements +
		      select_lex->group_list.elements,
		      (ORDER*) select_lex->order_list.first,
		      (ORDER*) select_lex->group_list.first,
		      select_lex->having,
		      (ORDER*) lex->proc_list.first,
238 239
		      select_lex->options | thd->options |
                      setup_tables_done_option,
unknown's avatar
af  
unknown committed
240 241
		      result, unit, select_lex);
  }
242 243
  DBUG_PRINT("info",("res: %d  report_error: %d", res,
		     thd->net.report_error));
unknown's avatar
unknown committed
244
  res|= thd->net.report_error;
245
  if (unlikely(res))
246
  {
247
    /* If we had a another error reported earlier then this will be ignored */
unknown's avatar
unknown committed
248
    result->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR));
249
    result->abort();
unknown's avatar
unknown committed
250
  }
251
  DBUG_RETURN(res);
252 253
}

254

255
/*
256
  Function to setup clauses without sum functions
257
*/
258 259
inline int setup_without_group(THD *thd, Item **ref_pointer_array,
			       TABLE_LIST *tables,
260
			       TABLE_LIST *leaves,
261 262 263 264 265 266
			       List<Item> &fields,
			       List<Item> &all_fields,
			       COND **conds,
			       ORDER *order,
			       ORDER *group, bool *hidden_group_fields)
{
unknown's avatar
af  
unknown committed
267 268 269 270 271
  bool save_allow_sum_func;
  int res;
  DBUG_ENTER("setup_without_group");

  save_allow_sum_func= thd->allow_sum_func;
272
  thd->allow_sum_func= 0;
unknown's avatar
unknown committed
273
  res= setup_conds(thd, tables, leaves, conds);
unknown's avatar
unknown committed
274 275 276 277 278 279
  thd->allow_sum_func= save_allow_sum_func;
  res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
                          order);
  thd->allow_sum_func= 0;
  res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields,
                          group, hidden_group_fields);
280
  thd->allow_sum_func= save_allow_sum_func;
unknown's avatar
af  
unknown committed
281
  DBUG_RETURN(res);
282 283
}

unknown's avatar
unknown committed
284
/*****************************************************************************
285 286
  Check fields, find best join, do the select and output fields.
  mysql_select assumes that all tables are already opened
unknown's avatar
unknown committed
287 288
*****************************************************************************/

289
/*
unknown's avatar
af  
unknown committed
290
  Prepare of whole select (including sub queries in future).
291 292 293
  return -1 on error
          0 on success
*/
unknown's avatar
unknown committed
294
int
295 296 297 298
JOIN::prepare(Item ***rref_pointer_array,
	      TABLE_LIST *tables_init,
	      uint wild_num, COND *conds_init, uint og_num,
	      ORDER *order_init, ORDER *group_init,
unknown's avatar
unknown committed
299
	      Item *having_init,
300 301
	      ORDER *proc_param_init, SELECT_LEX *select_lex_arg,
	      SELECT_LEX_UNIT *unit_arg)
unknown's avatar
unknown committed
302
{
303
  DBUG_ENTER("JOIN::prepare");
unknown's avatar
unknown committed
304

unknown's avatar
af  
unknown committed
305 306 307 308
  // to prevent double initialization on EXPLAIN
  if (optimized)
    DBUG_RETURN(0);

309 310 311 312 313 314
  conds= conds_init;
  order= order_init;
  group_list= group_init;
  having= having_init;
  proc_param= proc_param_init;
  tables_list= tables_init;
315
  select_lex= select_lex_arg;
316
  select_lex->join= this;
317
  join_list= &select_lex->top_join_list;
318
  union_part= (unit_arg->first_select()->next_select() != 0);
unknown's avatar
unknown committed
319

320 321 322 323 324 325 326
  /*
    If we have already executed SELECT, then it have not sense to prevent
    its table from update (see unique_table())
  */
  if (thd->derived_tables_processing)
    select_lex->exclude_from_table_unique_test= TRUE;

unknown's avatar
unknown committed
327 328
  /* Check that all tables, fields, conds and order are ok */

329 330 331
  if ((!(select_options & OPTION_SETUP_TABLES_DONE) &&
       setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables,
                    FALSE, FALSE)) ||
332
      setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
unknown's avatar
unknown committed
333
      select_lex->setup_ref_array(thd, og_num) ||
334 335
      setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
		   &all_fields, 1) ||
336 337 338
      setup_without_group(thd, (*rref_pointer_array), tables_list,
			  select_lex->leaf_tables, fields_list,
			  all_fields, &conds, order, group_list,
339
			  &hidden_group_fields))
unknown's avatar
unknown committed
340 341
    DBUG_RETURN(-1);				/* purecov: inspected */

342
  ref_pointer_array= *rref_pointer_array;
343
  
unknown's avatar
unknown committed
344 345 346 347
  if (having)
  {
    thd->where="having clause";
    thd->allow_sum_func=1;
unknown's avatar
unknown committed
348
    select_lex->having_fix_field= 1;
unknown's avatar
af  
unknown committed
349 350 351
    bool having_fix_rc= (!having->fixed &&
			 (having->fix_fields(thd, tables_list, &having) ||
			  having->check_cols(1)));
unknown's avatar
unknown committed
352
    select_lex->having_fix_field= 0;
unknown's avatar
unknown committed
353
    if (having_fix_rc || thd->net.report_error)
unknown's avatar
unknown committed
354 355
      DBUG_RETURN(-1);				/* purecov: inspected */
    if (having->with_sum_func)
356
      having->split_sum_func(thd, ref_pointer_array, all_fields);
unknown's avatar
unknown committed
357
  }
358

unknown's avatar
VIEW  
unknown committed
359
  if (!thd->lex->view_prepare_mode)
360 361
  {
    Item_subselect *subselect;
unknown's avatar
VIEW  
unknown committed
362
    /* Is it subselect? */
unknown's avatar
af  
unknown committed
363
    if ((subselect= select_lex->master_unit()->item))
364 365
    {
      Item_subselect::trans_res res;
366
      if ((res= subselect->select_transformer(this)) !=
367
	  Item_subselect::RES_OK)
unknown's avatar
af  
unknown committed
368
      {
unknown's avatar
VIEW  
unknown committed
369
        select_lex->fix_prepare_information(thd, &conds);
370
	DBUG_RETURN((res == Item_subselect::RES_ERROR));
unknown's avatar
af  
unknown committed
371
      }
372 373 374
    }
  }

375
  if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
unknown's avatar
unknown committed
376
    DBUG_RETURN(-1);
377 378
  

unknown's avatar
unknown committed
379 380 381 382 383
  /*
    Check if one one uses a not constant column with group functions
    and no GROUP BY.
    TODO:  Add check of calculation of GROUP functions and fields:
	   SELECT COUNT(*)+table.col1 from table1;
384
  */
unknown's avatar
unknown committed
385
  {
386
    if (!group_list)
unknown's avatar
unknown committed
387 388
    {
      uint flag=0;
389
      List_iterator_fast<Item> it(fields_list);
unknown's avatar
unknown committed
390 391 392 393 394
      Item *item;
      while ((item= it++))
      {
	if (item->with_sum_func)
	  flag|=1;
unknown's avatar
af  
unknown committed
395
	else if (!(flag & 2) && !item->const_during_execution())
unknown's avatar
unknown committed
396 397 398 399
	  flag|=2;
      }
      if (flag == 3)
      {
unknown's avatar
unknown committed
400 401
	my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
                   ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));
unknown's avatar
unknown committed
402 403 404
	DBUG_RETURN(-1);
      }
    }
405
    TABLE_LIST *table_ptr;
406 407 408
    for (table_ptr= select_lex->leaf_tables;
	 table_ptr;
	 table_ptr= table_ptr->next_leaf)
409
      tables++;
unknown's avatar
unknown committed
410
  }
411 412 413
  {
    /* Caclulate the number of groups */
    send_group_parts= 0;
414
    for (ORDER *group_tmp= group_list ; group_tmp ; group_tmp= group_tmp->next)
415 416 417
      send_group_parts++;
  }
  
418
  procedure= setup_procedure(thd, proc_param, result, fields_list, &error);
unknown's avatar
unknown committed
419
  if (error)
420
    goto err;					/* purecov: inspected */
unknown's avatar
unknown committed
421 422
  if (procedure)
  {
423 424
    if (setup_new_fields(thd, tables_list, fields_list, all_fields,
			 procedure->param_fields))
425
	goto err;				/* purecov: inspected */
unknown's avatar
unknown committed
426 427
    if (procedure->group)
    {
428
      if (!test_if_subpart(procedure->group,group_list))
unknown's avatar
unknown committed
429
      {						/* purecov: inspected */
unknown's avatar
unknown committed
430 431
	my_message(ER_DIFF_GROUPS_PROC, ER(ER_DIFF_GROUPS_PROC),
                   MYF(0));                     /* purecov: inspected */
432
	goto err;				/* purecov: inspected */
unknown's avatar
unknown committed
433 434 435
      }
    }
#ifdef NOT_NEEDED
436
    else if (!group_list && procedure->flags & PROC_GROUP)
unknown's avatar
unknown committed
437
    {
unknown's avatar
unknown committed
438
      my_message(ER_NO_GROUP_FOR_PROC, MYF(0));
439
      goto err;
unknown's avatar
unknown committed
440 441 442
    }
#endif
    if (order && (procedure->flags & PROC_NO_SORT))
443
    {						/* purecov: inspected */
unknown's avatar
unknown committed
444 445
      my_message(ER_ORDER_WITH_PROC, ER(ER_ORDER_WITH_PROC),
                 MYF(0));                       /* purecov: inspected */
446
      goto err;					/* purecov: inspected */
unknown's avatar
unknown committed
447 448 449 450
    }
  }

  /* Init join struct */
451
  count_field_types(&tmp_table_param, all_fields, 0);
452
  ref_pointer_array_size= all_fields.elements*sizeof(Item*);
453 454
  this->group= group_list != 0;
  row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
455
	      unit_arg->select_limit_cnt);
unknown's avatar
unknown committed
456
  /* select_limit is used to decide if we are likely to scan the whole table */
457
  select_limit= unit_arg->select_limit_cnt;
unknown's avatar
unknown committed
458 459
  if (having || (select_options & OPTION_FOUND_ROWS))
    select_limit= HA_POS_ERROR;
460 461
  do_send_rows = (unit_arg->select_limit_cnt) ? 1 : 0;
  unit= unit_arg;
unknown's avatar
unknown committed
462 463

#ifdef RESTRICTED_GROUP
464
  if (sum_func_count && !group_list && (func_count || field_count))
unknown's avatar
unknown committed
465
  {
unknown's avatar
unknown committed
466
    my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0));
467
    goto err;
unknown's avatar
unknown committed
468 469
  }
#endif
unknown's avatar
af  
unknown committed
470
  if (!procedure && result && result->prepare(fields_list, unit_arg))
471 472 473 474 475 476 477
    goto err;					/* purecov: inspected */

  if (select_lex->olap == ROLLUP_TYPE && rollup_init())
    goto err;
  if (alloc_func_list())
    goto err;

unknown's avatar
VIEW  
unknown committed
478
  select_lex->fix_prepare_information(thd, &conds);
479
  DBUG_RETURN(0); // All OK
480 481 482 483 484

err:
  delete procedure;				/* purecov: inspected */
  procedure= 0;
  DBUG_RETURN(-1);				/* purecov: inspected */
485
}
unknown's avatar
unknown committed
486

487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
/*
  test if it is known for optimisation IN subquery

  SYNOPSYS
    JOIN::test_in_subselect
    where - pointer for variable in which conditions should be
            stored if subquery is known

  RETURN
    1 - known
    0 - unknown
*/

bool JOIN::test_in_subselect(Item **where)
{
  if (conds->type() == Item::FUNC_ITEM &&
503
      ((Item_func *)this->conds)->functype() == Item_func::EQ_FUNC &&
504 505 506 507 508 509 510 511 512 513 514
      ((Item_func *)conds)->arguments()[0]->type() == Item::REF_ITEM &&
      ((Item_func *)conds)->arguments()[1]->type() == Item::FIELD_ITEM)
  {
    join_tab->info= "Using index";
    *where= 0;
    return 1;
  }
  if (conds->type() == Item::COND_ITEM &&
      ((class Item_func *)this->conds)->functype() ==
      Item_func::COND_AND_FUNC)
  {
515 516 517 518
    if ((*where= remove_additional_cond(conds)))
      join_tab->info= "Using index; Using where";
    else
      join_tab->info= "Using index";
519 520 521 522 523
    return 1;
  }
  return 0;
}

524 525 526
/*
  global select optimisation.
  return 0 - success
527
         1 - error
528 529 530 531 532 533
  error code saved in field 'error'
*/
int
JOIN::optimize()
{
  DBUG_ENTER("JOIN::optimize");
unknown's avatar
unknown committed
534
  // to prevent double initialization on EXPLAIN
535 536 537
  if (optimized)
    DBUG_RETURN(0);
  optimized= 1;
unknown's avatar
unknown committed
538

539
  // Ignore errors of execution if option IGNORE present
540
  if (thd->lex->ignore)
541
    thd->lex->current_select->no_error= 1;
unknown's avatar
unknown committed
542 543
#ifdef HAVE_REF_TO_FIELDS			// Not done yet
  /* Add HAVING to WHERE if possible */
544
  if (having && !group_list && !sum_func_count)
unknown's avatar
unknown committed
545 546 547
  {
    if (!conds)
    {
548 549
      conds= having;
      having= 0;
unknown's avatar
unknown committed
550 551 552
    }
    else if ((conds=new Item_cond_and(conds,having)))
    {
unknown's avatar
unknown committed
553 554 555 556
      /*
        Item_cond_and can't be fixed after creation, so we do not check
        conds->fixed
      */
unknown's avatar
unknown committed
557
      conds->fix_fields(thd, tables_list, &conds);
558
      conds->change_ref_to_fields(thd, tables_list);
559
      conds->top_level_item();
560
      having= 0;
unknown's avatar
unknown committed
561 562 563
    }
  }
#endif
unknown's avatar
unknown committed
564 565
  SELECT_LEX *sel= thd->lex->current_select;
  if (sel->first_cond_optimization)
566
  {
unknown's avatar
unknown committed
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
    /*
      The following code will allocate the new items in a permanent
      MEMROOT for prepared statements and stored procedures.
    */

    Item_arena *arena= thd->current_arena, backup;
    if (arena->is_conventional())
      arena= 0;                                   // For easier test
    else
      thd->set_n_backup_item_arena(arena, &backup);

    sel->first_cond_optimization= 0;

    /* Convert all outer joins to inner joins if possible */
    conds= simplify_joins(this, join_list, conds, TRUE);

    sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0;

    if (arena)
      thd->restore_backup_item_arena(arena, &backup);
587 588
  }

unknown's avatar
unknown committed
589
  conds= optimize_cond(this, conds, join_list, &cond_value);   
590
  if (thd->net.report_error)
unknown's avatar
unknown committed
591
  {
unknown's avatar
unknown committed
592
    error= 1;
593
    DBUG_PRINT("error",("Error from optimize_cond"));
594
    DBUG_RETURN(1);
unknown's avatar
unknown committed
595
  }
unknown's avatar
unknown committed
596

unknown's avatar
unknown committed
597 598
  if (cond_value == Item::COND_FALSE ||
      (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
unknown's avatar
unknown committed
599
  {						/* Impossible cond */
600
    DBUG_PRINT("info", ("Impossible WHERE"));
601
    zero_result_cause= "Impossible WHERE";
602
    error= 0;
603
    DBUG_RETURN(0);
unknown's avatar
unknown committed
604 605 606
  }

  /* Optimize count(*), min() and max() */
607
  if (tables_list && tmp_table_param.sum_func_count && ! group_list)
unknown's avatar
unknown committed
608 609
  {
    int res;
unknown's avatar
unknown committed
610
    /*
unknown's avatar
unknown committed
611 612
      opt_sum_query() returns -1 if no rows match to the WHERE conditions,
      or 1 if all items were resolved, or 0, or an error number HA_ERR_...
unknown's avatar
unknown committed
613
    */
614
    if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds)))
unknown's avatar
unknown committed
615
    {
unknown's avatar
unknown committed
616 617
      if (res > 1)
      {
618
        DBUG_PRINT("error",("Error from opt_sum_query"));
619
	DBUG_RETURN(1);
unknown's avatar
unknown committed
620
      }
unknown's avatar
unknown committed
621 622
      if (res < 0)
      {
623
        DBUG_PRINT("info",("No matching min/max row"));
624
	zero_result_cause= "No matching min/max row";
unknown's avatar
unknown committed
625
	error=0;
626
	DBUG_RETURN(0);
unknown's avatar
unknown committed
627
      }
628
      DBUG_PRINT("info",("Select tables optimized away"));
unknown's avatar
unknown committed
629
      zero_result_cause= "Select tables optimized away";
unknown's avatar
unknown committed
630
      tables_list= 0;				// All tables resolved
unknown's avatar
unknown committed
631 632
    }
  }
633
  if (!tables_list)
634
  {
635
    DBUG_PRINT("info",("No tables"));
636
    error= 0;
637
    DBUG_RETURN(0);
638
  }
unknown's avatar
unknown committed
639
  error= -1;					// Error is sent to client
640
  sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables);
unknown's avatar
unknown committed
641 642

  /* Calculate how to do the join */
643
  thd->proc_info= "statistics";
644
  if (make_join_statistics(this, select_lex->leaf_tables, conds, &keyuse) ||
645
      thd->is_fatal_error)
646 647
  {
    DBUG_PRINT("error",("Error: make_join_statistics() failed"));
unknown's avatar
unknown committed
648
    DBUG_RETURN(1);
649
  }
650

unknown's avatar
unknown committed
651 652
  /* Remove distinct if only const tables */
  select_distinct= select_distinct && (const_tables != tables);
653
  thd->proc_info= "preparing";
unknown's avatar
unknown committed
654
  if (result->initialize_tables(this))
unknown's avatar
unknown committed
655
  {
656 657
    DBUG_PRINT("error",("Error: initialize_tables() failed"));
    DBUG_RETURN(1);				// error == -1
unknown's avatar
unknown committed
658
  }
659
  if (const_table_map != found_const_table_map &&
unknown's avatar
af  
unknown committed
660 661 662 663
      !(select_options & SELECT_DESCRIBE) &&
      (!conds ||
       !(conds->used_tables() & RAND_TABLE_BIT) ||
       select_lex->master_unit() == &thd->lex->unit)) // upper level SELECT
unknown's avatar
unknown committed
664
  {
unknown's avatar
unknown committed
665
    zero_result_cause= "no matching row in const table";
666 667
    DBUG_PRINT("error",("Error: %s", zero_result_cause));
    error= 0;
668
    DBUG_RETURN(0);
unknown's avatar
unknown committed
669 670
  }
  if (!(thd->options & OPTION_BIG_SELECTS) &&
unknown's avatar
unknown committed
671
      best_read > (double) thd->variables.max_join_size &&
unknown's avatar
unknown committed
672 673
      !(select_options & SELECT_DESCRIBE))
  {						/* purecov: inspected */
674
    my_message(ER_TOO_BIG_SELECT, ER(ER_TOO_BIG_SELECT), MYF(0));
675
    error= -1;
unknown's avatar
unknown committed
676
    DBUG_RETURN(1);
unknown's avatar
unknown committed
677
  }
678
  if (const_tables && !thd->locked_tables &&
unknown's avatar
unknown committed
679
      !(select_options & SELECT_NO_UNLOCK))
680
    mysql_unlock_some_tables(thd, table, const_tables);
681
  if (!conds && outer_join)
682 683 684 685
  {
    /* Handle the case where we have an OUTER JOIN without a WHERE */
    conds=new Item_int((longlong) 1,1);	// Always true
  }
unknown's avatar
unknown committed
686 687
  select= make_select(*table, const_table_map,
                      const_table_map, conds, 1, &error);
unknown's avatar
unknown committed
688
  if (error)
unknown's avatar
unknown committed
689 690
  {						/* purecov: inspected */
    error= -1;					/* purecov: inspected */
691
    DBUG_PRINT("error",("Error: make_select() failed"));
unknown's avatar
unknown committed
692
    DBUG_RETURN(1);
unknown's avatar
unknown committed
693
  }
694 695 696

  make_outerjoin_info(this);

unknown's avatar
unknown committed
697 698 699 700 701 702 703 704 705 706
  /*
    Among the equal fields belonging to the same multiple equality
    choose the one that is to be retrieved first and substitute
    all references to these in where condition for a reference for
    the selected field.
  */
  if (conds)
  {
    conds= substitute_for_best_equal_field(conds, cond_equal, map2table);
    conds->update_used_tables();
unknown's avatar
unknown committed
707
    DBUG_EXECUTE("where", print_where(conds, "after substitute_best_equal"););
unknown's avatar
unknown committed
708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
  }
  /*
    Permorm the the optimization on fields evaluation mentioned above
    for all on expressions.
  */ 
  for (JOIN_TAB *tab= join_tab + const_tables; tab < join_tab + tables ; tab++)
  {
    if (*tab->on_expr_ref)
    {
      *tab->on_expr_ref= substitute_for_best_equal_field(*tab->on_expr_ref,
                                                         tab->cond_equal,
                                                         map2table);
      (*tab->on_expr_ref)->update_used_tables();
    }
  }

724
  if (make_join_select(this, select, conds))
unknown's avatar
unknown committed
725
  {
726 727
    zero_result_cause=
      "Impossible WHERE noticed after reading const tables";
728
    DBUG_RETURN(0);				// error == 0
unknown's avatar
unknown committed
729 730 731 732 733
  }

  error= -1;					/* if goto err */

  /* Optimize distinct away if possible */
unknown's avatar
unknown committed
734 735
  {
    ORDER *org_order= order;
unknown's avatar
unknown committed
736
    order=remove_const(this, order,conds,&simple_order);
unknown's avatar
unknown committed
737 738 739 740 741 742 743
    /*
      If we are using ORDER BY NULL or ORDER BY const_expression,
      return result in any order (even if we are using a GROUP BY)
    */
    if (!order && org_order)
      skip_sort_order= 1;
  }
744
  if (group_list || tmp_table_param.sum_func_count)
unknown's avatar
unknown committed
745 746 747 748
  {
    if (! hidden_group_fields)
      select_distinct=0;
  }
unknown's avatar
unknown committed
749
  else if (select_distinct && tables - const_tables == 1)
unknown's avatar
unknown committed
750
  {
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
    /*
      We are only using one table. In this case we change DISTINCT to a
      GROUP BY query if:
      - The GROUP BY can be done through indexes (no sort) and the ORDER
        BY only uses selected fields.
	(In this case we can later optimize away GROUP BY and ORDER BY)
      - We are scanning the whole table without LIMIT
        This can happen if:
        - We are using CALC_FOUND_ROWS
        - We are using an ORDER BY that can't be optimized away.

      We don't want to use this optimization when we are using LIMIT
      because in this case we can just create a temporary table that
      holds LIMIT rows and stop when this table is full.
    */
unknown's avatar
unknown committed
766
    JOIN_TAB *tab= &join_tab[const_tables];
767 768 769
    bool all_order_fields_used;
    if (order)
      skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1);
unknown's avatar
unknown committed
770 771
    if ((group_list=create_distinct_group(thd, order, fields_list,
				          &all_order_fields_used)))
772 773
    {
      bool skip_group= (skip_sort_order &&
unknown's avatar
unknown committed
774
			test_if_skip_sort_order(tab, group_list, select_limit,
775 776 777 778 779 780 781 782 783
						1) != 0);
      if ((skip_group && all_order_fields_used) ||
	  select_limit == HA_POS_ERROR ||
	  (order && !skip_sort_order))
      {
	/*  Change DISTINCT to GROUP BY */
	select_distinct= 0;
	no_order= !order;
	if (all_order_fields_used)
784 785 786 787 788 789
	{
	  if (order && skip_sort_order)
	  {
	    /*
	      Force MySQL to read the table in sorted order to get result in
	      ORDER BY order.
unknown's avatar
unknown committed
790
	    */
unknown's avatar
unknown committed
791
	    tmp_table_param.quick_group=0;
792
	  }
793
	  order=0;
unknown's avatar
unknown committed
794
        }
unknown's avatar
unknown committed
795
	group=1;				// For end_write_group
796 797
      }
      else
unknown's avatar
unknown committed
798
	group_list= 0;
unknown's avatar
unknown committed
799
    }
800
    else if (thd->is_fatal_error)			// End of memory
unknown's avatar
unknown committed
801
      DBUG_RETURN(1);
unknown's avatar
unknown committed
802
  }
803 804 805
  simple_group= 0;
  if (rollup.state == ROLLUP::STATE_NONE)
    group_list= remove_const(this, group_list, conds, &simple_group);
806
  if (!group_list && group)
unknown's avatar
unknown committed
807 808 809 810 811
  {
    order=0;					// The output has only one row
    simple_order=1;
  }

812 813
  calc_group_buffer(this, group_list);
  send_group_parts= tmp_table_param.group_parts; /* Save org parts */
unknown's avatar
unknown committed
814 815
  if (procedure && procedure->group)
  {
816 817 818
    group_list= procedure->group= remove_const(this, procedure->group, conds,
					       &simple_group);
    calc_group_buffer(this, group_list);
unknown's avatar
unknown committed
819 820
  }

821 822
  if (test_if_subpart(group_list, order) ||
      (!group_list && tmp_table_param.sum_func_count))
unknown's avatar
unknown committed
823 824
    order=0;

unknown's avatar
unknown committed
825
  // Can't use sort on head table if using row cache
826
  if (full_join)
unknown's avatar
unknown committed
827
  {
828
    if (group_list)
unknown's avatar
unknown committed
829 830 831 832 833
      simple_group=0;
    if (order)
      simple_order=0;
  }

834 835 836 837 838 839 840 841 842
  /*
    Check if we need to create a temporary table.
    This has to be done if all tables are not already read (const tables)
    and one of the following conditions holds:
    - We are using DISTINCT (simple distinct's are already optimized away)
    - We are using an ORDER BY or GROUP BY on fields not in the first table
    - We are using different ORDER BY and GROUP BY orders
    - The user wants us to buffer the result.
  */
843
  need_tmp= (const_tables != tables &&
unknown's avatar
unknown committed
844
	     ((select_distinct || !simple_order || !simple_group) ||
unknown's avatar
unknown committed
845
	      (group_list && order) ||
846
	      test(select_options & OPTION_BUFFER_RESULT)));
unknown's avatar
unknown committed
847

unknown's avatar
unknown committed
848
  // No cache for MATCH
849
  make_join_readinfo(this,
unknown's avatar
unknown committed
850
		     (select_options & (SELECT_DESCRIBE |
851
					SELECT_NO_JOIN_CACHE)) |
unknown's avatar
unknown committed
852
		     (select_lex->ftfunc_list->elements ?
853
		      SELECT_NO_JOIN_CACHE : 0));
unknown's avatar
unknown committed
854

855 856 857 858
  /* Perform FULLTEXT search before all regular searches */
  if (!(select_options & SELECT_DESCRIBE))
    init_ftfuncs(thd, select_lex, test(order));

859 860 861
  /*
    is this simple IN subquery?
  */
862
  if (!group_list && !order &&
863
      unit->item && unit->item->substype() == Item_subselect::IN_SUBS &&
864
      tables == 1 && conds &&
865 866
      !unit->first_select()->next_select())
  {
867
    if (!having)
868
    {
869
      Item *where= 0;
870 871
      if (join_tab[0].type == JT_EQ_REF &&
	  join_tab[0].ref.items[0]->name == in_left_expr_name)
872
      {
873 874
	if (test_in_subselect(&where))
	{
875
	  join_tab[0].type= JT_UNIQUE_SUBQUERY;
876 877
	  error= 0;
	  DBUG_RETURN(unit->item->
878 879 880 881 882
		      change_engine(new
				    subselect_uniquesubquery_engine(thd,
								    join_tab,
								    unit->item,
								    where)));
883
	}
884
      }
885 886
      else if (join_tab[0].type == JT_REF &&
	       join_tab[0].ref.items[0]->name == in_left_expr_name)
887
      {
888 889
	if (test_in_subselect(&where))
	{
890
	  join_tab[0].type= JT_INDEX_SUBQUERY;
891 892
	  error= 0;
	  DBUG_RETURN(unit->item->
893 894 895 896 897 898
		      change_engine(new
				    subselect_indexsubquery_engine(thd,
								   join_tab,
								   unit->item,
								   where,
								   0)));
899
	}
900
      }
901
    } else if (join_tab[0].type == JT_REF_OR_NULL &&
902
	       join_tab[0].ref.items[0]->name == in_left_expr_name &&
903 904 905 906
	       having->type() == Item::FUNC_ITEM &&
	       ((Item_func *) having)->functype() ==
	       Item_func::ISNOTNULLTEST_FUNC)
    {
907
      join_tab[0].type= JT_INDEX_SUBQUERY;
908
      error= 0;
909 910 911 912 913

      if ((conds= remove_additional_cond(conds)))
	join_tab->info= "Using index; Using where";
      else
	join_tab->info= "Using index";
914

915
      DBUG_RETURN(unit->item->
916 917 918 919 920
		  change_engine(new subselect_indexsubquery_engine(thd,
								   join_tab,
								   unit->item,
								   conds,
								   1)));
921
    }
922

923
  }
924 925 926 927 928 929 930
  /*
    Need to tell Innobase that to play it safe, it should fetch all
    columns of the tables: this is because MySQL may build row
    pointers for the rows, and for all columns of the primary key the
    field->query_id has not necessarily been set to thd->query_id by
    MySQL.
  */
unknown's avatar
unknown committed
931 932

#ifdef HAVE_INNOBASE_DB
933
  if (need_tmp || select_distinct || group_list || order)
unknown's avatar
unknown committed
934
  {
935
    for (uint i_h = const_tables; i_h < tables; i_h++)
unknown's avatar
unknown committed
936
    {
937
      TABLE* table_h = join_tab[i_h].table;
unknown's avatar
af  
unknown committed
938
      table_h->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
unknown's avatar
unknown committed
939 940 941 942
    }
  }
#endif

943
  DBUG_EXECUTE("info",TEST_join(this););
unknown's avatar
unknown committed
944 945 946 947 948
  /*
    Because filesort always does a full table scan or a quick range scan
    we must add the removed reference to the select for the table.
    We only need to do this when we have a simple_order or simple_group
    as in other cases the join is done before the sort.
949
  */
950
  if (const_tables != tables &&
951
      (order || group_list) &&
unknown's avatar
af  
unknown committed
952
      join_tab[const_tables].type != JT_ALL &&
953
      join_tab[const_tables].type != JT_FT &&
unknown's avatar
af  
unknown committed
954
      join_tab[const_tables].type != JT_REF_OR_NULL &&
955
      (order && simple_order || group_list && simple_group))
unknown's avatar
unknown committed
956
  {
957
    if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
unknown's avatar
unknown committed
958
      DBUG_RETURN(1);
unknown's avatar
unknown committed
959 960 961
  }

  if (!(select_options & SELECT_BIG_RESULT) &&
962
      ((group_list && const_tables != tables &&
963
	(!simple_group ||
964
	 !test_if_skip_sort_order(&join_tab[const_tables], group_list,
965
				  unit->select_limit_cnt, 0))) ||
unknown's avatar
unknown committed
966
       select_distinct) &&
967
      tmp_table_param.quick_group && !procedure)
unknown's avatar
unknown committed
968 969 970
  {
    need_tmp=1; simple_order=simple_group=0;	// Force tmp table without sort
  }
971

unknown's avatar
unknown committed
972
  tmp_having= having;
973
  if (select_options & SELECT_DESCRIBE)
974 975
  {
    error= 0;
976
    DBUG_RETURN(0);
977
  }
978 979 980 981 982 983 984 985 986
  having= 0;

  /* Create a tmp table if distinct or if the sort is too complicated */
  if (need_tmp)
  {
    DBUG_PRINT("info",("Creating tmp table"));
    thd->proc_info="Creating tmp table";

    init_items_ref_array();
987

988 989 990 991 992 993 994 995 996 997 998
    tmp_table_param.hidden_field_count= (all_fields.elements -
					 fields_list.elements);
    if (!(exec_tmp_table1 =
	  create_tmp_table(thd, &tmp_table_param, all_fields,
			   ((!simple_group && !procedure &&
			     !(test_flags & TEST_NO_KEY_GROUP)) ?
			    group_list : (ORDER*) 0),
			   group_list ? 0 : select_distinct,
			   group_list && simple_group,
			   select_options,
			   (order == 0 || skip_sort_order) ? select_limit :
999 1000
			   HA_POS_ERROR,
			   (char *) "")))
1001
      DBUG_RETURN(1);
1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012

    /*
      We don't have to store rows in temp table that doesn't match HAVING if:
      - we are sorting the table and writing complete group rows to the
        temp table.
      - We are using DISTINCT without resolving the distinct as a GROUP BY
        on all columns.
      
      If having is not handled here, it will be checked before the row
      is sent to the client.
    */    
unknown's avatar
unknown committed
1013
    if (tmp_having && 
1014 1015 1016 1017 1018 1019 1020 1021
	(sort_and_group || (exec_tmp_table1->distinct && !group_list)))
      having= tmp_having;

    /* if group or order on first table, sort first */
    if (group_list && simple_group)
    {
      DBUG_PRINT("info",("Sorting for group"));
      thd->proc_info="Sorting for group";
1022
      if (create_sort_index(thd, this, group_list,
1023
			    HA_POS_ERROR, HA_POS_ERROR) ||
1024
	  alloc_group_fields(this, group_list) ||
1025 1026
          make_sum_func_list(all_fields, fields_list, 1) ||
          setup_sum_funcs(thd, sum_funcs))
1027 1028 1029 1030 1031
	DBUG_RETURN(1);
      group_list=0;
    }
    else
    {
1032 1033
      if (make_sum_func_list(all_fields, fields_list, 0) ||
          setup_sum_funcs(thd, sum_funcs))
1034 1035 1036 1037 1038
	DBUG_RETURN(1);
      if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
      {
	DBUG_PRINT("info",("Sorting for order"));
	thd->proc_info="Sorting for order";
1039
	if (create_sort_index(thd, this, order,
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
                              HA_POS_ERROR, HA_POS_ERROR))
	  DBUG_RETURN(1);
	order=0;
      }
    }
    
    /*
      Optimize distinct when used on some of the tables
      SELECT DISTINCT t1.a FROM t1,t2 WHERE t1.b=t2.b
      In this case we can stop scanning t2 when we have found one t1.a
    */

    if (exec_tmp_table1->distinct)
    {
      table_map used_tables= thd->used_tables;
1055
      JOIN_TAB *last_join_tab= join_tab+tables-1;
1056 1057
      do
      {
1058
	if (used_tables & last_join_tab->table->map)
1059
	  break;
1060 1061
	last_join_tab->not_used_in_distinct=1;
      } while (last_join_tab-- != join_tab);
1062 1063 1064 1065
      /* Optimize "select distinct b from t1 order by key_part_1 limit #" */
      if (order && skip_sort_order)
      {
 	/* Should always succeed */
1066
	if (test_if_skip_sort_order(&join_tab[const_tables],
1067 1068 1069 1070 1071
				    order, unit->select_limit_cnt, 0))
	  order=0;
      }
    }
    
1072
    if (thd->lex->subqueries)
1073 1074 1075
    {
      if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
	DBUG_RETURN(-1);
1076
      error= 0;				// Ensure that tmp_join.error= 0
1077 1078 1079 1080
      restore_tmp();
    }
  }

1081
  error= 0;
1082 1083 1084
  DBUG_RETURN(0);
}

1085

1086
/*
1087
  Restore values in temporary join
1088
*/
1089
void JOIN::restore_tmp()
1090
{
1091
  memcpy(tmp_join, this, (size_t) sizeof(JOIN));
1092 1093
}

1094

1095 1096 1097 1098
int
JOIN::reinit()
{
  DBUG_ENTER("JOIN::reinit");
1099
  /* TODO move to unit reinit */
unknown's avatar
af  
unknown committed
1100
  unit->set_limit(select_lex, select_lex);
unknown's avatar
VIEW  
unknown committed
1101 1102 1103 1104

  /* conds should not be used here, it is added just for safety */
  if (tables_list)
  {
unknown's avatar
unknown committed
1105 1106
    if (setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables,
                     TRUE, FALSE))
unknown's avatar
VIEW  
unknown committed
1107 1108 1109
      DBUG_RETURN(1);
  }

1110
  /* Reset of sum functions */
unknown's avatar
unknown committed
1111
  first_record= 0;
unknown's avatar
unknown committed
1112

1113 1114 1115 1116 1117
  if (exec_tmp_table1)
  {
    exec_tmp_table1->file->extra(HA_EXTRA_RESET_STATE);
    exec_tmp_table1->file->delete_all_rows();
    free_io_cache(exec_tmp_table1);
unknown's avatar
unknown committed
1118
    filesort_free_buffers(exec_tmp_table1);
1119 1120 1121 1122 1123 1124
  }
  if (exec_tmp_table2)
  {
    exec_tmp_table2->file->extra(HA_EXTRA_RESET_STATE);
    exec_tmp_table2->file->delete_all_rows();
    free_io_cache(exec_tmp_table2);
unknown's avatar
unknown committed
1125
    filesort_free_buffers(exec_tmp_table2);
1126 1127
  }
  if (items0)
1128
    set_items_ref_array(items0);
1129

1130 1131 1132
  if (join_tab_save)
    memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * tables);

1133 1134 1135
  if (tmp_join)
    restore_tmp();

unknown's avatar
af  
unknown committed
1136 1137 1138 1139 1140 1141 1142
  if (sum_funcs)
  {
    Item_sum *func, **func_ptr= sum_funcs;
    while ((func= *(func_ptr++)))
      func->clear();
  }

1143 1144 1145
  DBUG_RETURN(0);
}

1146 1147 1148 1149

bool
JOIN::save_join_tab()
{
unknown's avatar
unknown committed
1150
  if (!join_tab_save && select_lex->master_unit()->uncacheable)
1151
  {
unknown's avatar
unknown committed
1152 1153
    if (!(join_tab_save= (JOIN_TAB*)thd->memdup((gptr) join_tab,
						sizeof(JOIN_TAB) * tables)))
1154 1155 1156 1157 1158 1159
      return 1;
  }
  return 0;
}


1160
/*
1161
  Exec select
1162 1163 1164 1165 1166 1167
*/
void
JOIN::exec()
{
  int      tmp_error;
  DBUG_ENTER("JOIN::exec");
1168

1169
  error= 0;
unknown's avatar
unknown committed
1170 1171 1172 1173
  if (procedure)
  {
    if (procedure->change_columns(fields_list) ||
	result->prepare(fields_list, unit))
1174 1175
    {
      thd->limit_found_rows= thd->examined_row_count= 0;
unknown's avatar
unknown committed
1176
      DBUG_VOID_RETURN;
1177
    }
unknown's avatar
unknown committed
1178
  }
1179
  (void) result->prepare2(); // Currently, this cannot fail.
1180

unknown's avatar
unknown committed
1181
  if (!tables_list)
1182 1183
  {                                           // Only test of functions
    if (select_options & SELECT_DESCRIBE)
unknown's avatar
af  
unknown committed
1184
      select_describe(this, FALSE, FALSE, FALSE,
unknown's avatar
unknown committed
1185
		      (zero_result_cause?zero_result_cause:"No tables used"));
1186 1187
    else
    {
1188 1189
      result->send_fields(fields_list,
                          Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
1190 1191
      if (!having || having->val_int())
      {
1192 1193 1194
	if (do_send_rows && (procedure ? (procedure->send_row(fields_list) ||
                                          procedure->end_of_records())
                                       : result->send_data(fields_list)))
unknown's avatar
unknown committed
1195
	  error= 1;
1196
	else
1197
	{
unknown's avatar
unknown committed
1198
	  error= (int) result->send_eof();
1199 1200
	  send_records=1;
	}
1201 1202
      }
      else
1203
	error=(int) result->send_eof();
1204
    }
1205 1206 1207
    /* Single select (without union and limit) always returns 1 row */
    thd->limit_found_rows= 1;
    thd->examined_row_count= 0;
1208 1209
    DBUG_VOID_RETURN;
  }
1210
  thd->limit_found_rows= thd->examined_row_count= 0;
1211 1212 1213

  if (zero_result_cause)
  {
1214
    (void) return_zero_rows(this, result, select_lex->leaf_tables, fields_list,
unknown's avatar
af  
unknown committed
1215
			    send_row_on_empty_set(),
unknown's avatar
unknown committed
1216 1217
			    select_options,
			    zero_result_cause,
1218
			    having, procedure,
unknown's avatar
unknown committed
1219
			    unit);
1220 1221 1222
    DBUG_VOID_RETURN;
  }

unknown's avatar
unknown committed
1223 1224
  if (select_options & SELECT_DESCRIBE)
  {
unknown's avatar
unknown committed
1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
    /*
      Check if we managed to optimize ORDER BY away and don't use temporary
      table to resolve ORDER BY: in that case, we only may need to do
      filesort for GROUP BY.
    */
    if (!order && !no_order && (!skip_sort_order || !need_tmp))
    {
      /*
	Reset 'order' to 'group_list' and reinit variables describing
	'order'
      */
      order= group_list;
      simple_order= simple_group;
      skip_sort_order= 0;
    }
unknown's avatar
unknown committed
1240
    if (order &&
1241
	(const_tables == tables ||
unknown's avatar
unknown committed
1242
 	 ((simple_order || skip_sort_order) &&
1243
	  test_if_skip_sort_order(&join_tab[const_tables], order,
1244
				  select_limit, 0))))
unknown's avatar
unknown committed
1245
      order=0;
1246
    having= tmp_having;
1247
    select_describe(this, need_tmp,
1248
		    order != 0 && !skip_sort_order,
unknown's avatar
unknown committed
1249
		    select_distinct);
1250
    DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1251 1252
  }

1253 1254 1255 1256
  JOIN *curr_join= this;
  List<Item> *curr_all_fields= &all_fields;
  List<Item> *curr_fields_list= &fields_list;
  TABLE *curr_tmp_table= 0;
1257

1258 1259 1260 1261 1262 1263
  if ((curr_join->select_lex->options & OPTION_SCHEMA_TABLE) &&
      get_schema_tables_result(curr_join))
  {
    DBUG_VOID_RETURN;
  }

unknown's avatar
unknown committed
1264 1265 1266
  /* Create a tmp table if distinct or if the sort is too complicated */
  if (need_tmp)
  {
1267 1268 1269
    if (tmp_join)
      curr_join= tmp_join;
    curr_tmp_table= exec_tmp_table1;
unknown's avatar
unknown committed
1270 1271

    /* Copy data to the temporary table */
1272
    thd->proc_info= "Copying to tmp table";
unknown's avatar
unknown committed
1273
    DBUG_PRINT("info", ("%s", thd->proc_info));
1274
    if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
1275
    {
1276 1277
      error= tmp_error;
      DBUG_VOID_RETURN;
1278
    }
1279 1280 1281 1282 1283
    curr_tmp_table->file->info(HA_STATUS_VARIABLE);
    
    if (curr_join->having)
      curr_join->having= curr_join->tmp_having= 0; // Allready done
    
unknown's avatar
unknown committed
1284
    /* Change sum_fields reference to calculated fields in tmp_table */
1285 1286
    curr_join->all_fields= *curr_all_fields;
    if (!items1)
unknown's avatar
unknown committed
1287
    {
1288 1289 1290
      items1= items0 + all_fields.elements;
      if (sort_and_group || curr_tmp_table->group)
      {
1291
	if (change_to_use_tmp_fields(thd, items1,
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
				     tmp_fields_list1, tmp_all_fields1,
				     fields_list.elements, all_fields))
	  DBUG_VOID_RETURN;
      }
      else
      {
	if (change_refs_to_tmp_fields(thd, items1,
				      tmp_fields_list1, tmp_all_fields1,
				      fields_list.elements, all_fields))
	  DBUG_VOID_RETURN;
      }
      curr_join->tmp_all_fields1= tmp_all_fields1;
      curr_join->tmp_fields_list1= tmp_fields_list1;
      curr_join->items1= items1;
    }
    curr_all_fields= &tmp_all_fields1;
    curr_fields_list= &tmp_fields_list1;
1309
    set_items_ref_array(items1);
1310 1311 1312 1313 1314 1315 1316 1317
    
    if (sort_and_group || curr_tmp_table->group)
    {
      curr_join->tmp_table_param.field_count+= 
	curr_join->tmp_table_param.sum_func_count+
	curr_join->tmp_table_param.func_count;
      curr_join->tmp_table_param.sum_func_count= 
	curr_join->tmp_table_param.func_count= 0;
unknown's avatar
unknown committed
1318 1319 1320
    }
    else
    {
1321 1322 1323
      curr_join->tmp_table_param.field_count+= 
	curr_join->tmp_table_param.func_count;
      curr_join->tmp_table_param.func_count= 0;
unknown's avatar
unknown committed
1324
    }
1325 1326
    
    // procedure can't be used inside subselect => we do nothing special for it
unknown's avatar
unknown committed
1327 1328
    if (procedure)
      procedure->update_refs();
1329 1330
    
    if (curr_tmp_table->group)
unknown's avatar
unknown committed
1331
    {						// Already grouped
unknown's avatar
unknown committed
1332
      if (!curr_join->order && !curr_join->no_order && !skip_sort_order)
1333 1334
	curr_join->order= curr_join->group_list;  /* order by group */
      curr_join->group_list= 0;
unknown's avatar
unknown committed
1335
    }
1336
    
unknown's avatar
unknown committed
1337
    /*
1338 1339 1340 1341 1342
      If we have different sort & group then we must sort the data by group
      and copy it to another tmp table
      This code is also used if we are using distinct something
      we haven't been able to store in the temporary table yet
      like SEC_TO_TIME(SUM(...)).
unknown's avatar
unknown committed
1343 1344
    */

1345 1346 1347 1348 1349
    if (curr_join->group_list && (!test_if_subpart(curr_join->group_list,
						   curr_join->order) || 
				  curr_join->select_distinct) ||
	(curr_join->select_distinct &&
	 curr_join->tmp_table_param.using_indirect_summary_function))
unknown's avatar
unknown committed
1350 1351
    {					/* Must copy to another table */
      DBUG_PRINT("info",("Creating group table"));
1352
      
unknown's avatar
unknown committed
1353
      /* Free first data from old join */
1354
      curr_join->join_free(0);
1355
      if (make_simple_join(curr_join, curr_tmp_table))
unknown's avatar
unknown committed
1356
	DBUG_VOID_RETURN;
1357
      calc_group_buffer(curr_join, group_list);
1358 1359
      count_field_types(&curr_join->tmp_table_param,
			curr_join->tmp_all_fields1,
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378
			curr_join->select_distinct && !curr_join->group_list);
      curr_join->tmp_table_param.hidden_field_count= 
	(curr_join->tmp_all_fields1.elements-
	 curr_join->tmp_fields_list1.elements);
      
      
      if (exec_tmp_table2)
	curr_tmp_table= exec_tmp_table2;
      else
      {
	/* group data to new table */
	if (!(curr_tmp_table=
	      exec_tmp_table2= create_tmp_table(thd,
						&curr_join->tmp_table_param,
						*curr_all_fields,
						(ORDER*) 0,
						curr_join->select_distinct && 
						!curr_join->group_list,
						1, curr_join->select_options,
1379 1380
						HA_POS_ERROR,
						(char *) "")))
1381 1382 1383
	  DBUG_VOID_RETURN;
	curr_join->exec_tmp_table2= exec_tmp_table2;
      }
1384
      if (curr_join->group_list)
unknown's avatar
unknown committed
1385
      {
1386
	thd->proc_info= "Creating sort index";
1387 1388 1389 1390
	if (curr_join->join_tab == join_tab && save_join_tab())
	{
	  DBUG_VOID_RETURN;
	}
1391
	if (create_sort_index(thd, curr_join, curr_join->group_list,
1392
			      HA_POS_ERROR, HA_POS_ERROR) ||
1393
	    make_group_fields(this, curr_join))
unknown's avatar
unknown committed
1394
	{
1395
	  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1396 1397
	}
      }
1398
      
unknown's avatar
unknown committed
1399
      thd->proc_info="Copying to group table";
unknown's avatar
unknown committed
1400
      DBUG_PRINT("info", ("%s", thd->proc_info));
1401
      tmp_error= -1;
1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
      if (curr_join != this)
      {
	if (sum_funcs2)
	{
	  curr_join->sum_funcs= sum_funcs2;
	  curr_join->sum_funcs_end= sum_funcs_end2; 
	}
	else
	{
	  curr_join->alloc_func_list();
	  sum_funcs2= curr_join->sum_funcs;
	  sum_funcs_end2= curr_join->sum_funcs_end;
	}
      }
1416
      if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1417 1418 1419 1420
					1, TRUE))
        DBUG_VOID_RETURN;
      curr_join->group_list= 0;
      if (setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
1421 1422
	  (tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
				0)))
unknown's avatar
unknown committed
1423
      {
1424
	error= tmp_error;
1425
	DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1426
      }
1427 1428 1429 1430 1431 1432 1433 1434
      end_read_record(&curr_join->join_tab->read_record);
      curr_join->const_tables= curr_join->tables; // Mark free for join_free()
      curr_join->join_tab[0].table= 0;           // Table is freed
      
      // No sum funcs anymore
      if (!items2)
      {
	items2= items1 + all_fields.elements;
1435
	if (change_to_use_tmp_fields(thd, items2,
1436 1437 1438 1439 1440 1441 1442 1443
				     tmp_fields_list2, tmp_all_fields2, 
				     fields_list.elements, tmp_all_fields1))
	  DBUG_VOID_RETURN;
	curr_join->tmp_fields_list2= tmp_fields_list2;
	curr_join->tmp_all_fields2= tmp_all_fields2;
      }
      curr_fields_list= &curr_join->tmp_fields_list2;
      curr_all_fields= &curr_join->tmp_all_fields2;
1444
      set_items_ref_array(items2);
1445 1446 1447 1448 1449 1450 1451
      curr_join->tmp_table_param.field_count+= 
	curr_join->tmp_table_param.sum_func_count;
      curr_join->tmp_table_param.sum_func_count= 0;
    }
    if (curr_tmp_table->distinct)
      curr_join->select_distinct=0;		/* Each row is unique */
    
1452
    curr_join->join_free(0);			/* Free quick selects */
1453
    if (curr_join->select_distinct && ! curr_join->group_list)
unknown's avatar
unknown committed
1454 1455
    {
      thd->proc_info="Removing duplicates";
1456 1457 1458
      if (curr_join->tmp_having)
	curr_join->tmp_having->update_used_tables();
      if (remove_duplicates(curr_join, curr_tmp_table,
unknown's avatar
unknown committed
1459
			    *curr_fields_list, curr_join->tmp_having))
1460
	DBUG_VOID_RETURN;
1461 1462
      curr_join->tmp_having=0;
      curr_join->select_distinct=0;
unknown's avatar
unknown committed
1463
    }
1464 1465
    curr_tmp_table->reginfo.lock_type= TL_UNLOCK;
    if (make_simple_join(curr_join, curr_tmp_table))
1466
      DBUG_VOID_RETURN;
1467 1468 1469
    calc_group_buffer(curr_join, curr_join->group_list);
    count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0);
    
unknown's avatar
unknown committed
1470 1471
  }
  if (procedure)
1472 1473 1474
    count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0);
  
  if (curr_join->group || curr_join->tmp_table_param.sum_func_count ||
unknown's avatar
unknown committed
1475 1476
      (procedure && (procedure->flags & PROC_GROUP)))
  {
1477 1478 1479 1480
    if (make_group_fields(this, curr_join))
    {
      DBUG_VOID_RETURN;
    }
1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504
    if (!items3)
    {
      if (!items0)
	init_items_ref_array();
      items3= ref_pointer_array + (all_fields.elements*4);
      setup_copy_fields(thd, &curr_join->tmp_table_param,
			items3, tmp_fields_list3, tmp_all_fields3,
			curr_fields_list->elements, *curr_all_fields);
      tmp_table_param.save_copy_funcs= curr_join->tmp_table_param.copy_funcs;
      tmp_table_param.save_copy_field= curr_join->tmp_table_param.copy_field;
      tmp_table_param.save_copy_field_end=
	curr_join->tmp_table_param.copy_field_end;
      curr_join->tmp_all_fields3= tmp_all_fields3;
      curr_join->tmp_fields_list3= tmp_fields_list3;
    }
    else
    {
      curr_join->tmp_table_param.copy_funcs= tmp_table_param.save_copy_funcs;
      curr_join->tmp_table_param.copy_field= tmp_table_param.save_copy_field;
      curr_join->tmp_table_param.copy_field_end=
	tmp_table_param.save_copy_field_end;
    }
    curr_fields_list= &tmp_fields_list3;
    curr_all_fields= &tmp_all_fields3;
1505
    set_items_ref_array(items3);
1506

1507
    if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1508 1509 1510
				      1, TRUE) || 
        setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
        thd->is_fatal_error)
1511
      DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1512
  }
1513
  if (curr_join->group_list || curr_join->order)
unknown's avatar
unknown committed
1514 1515 1516 1517
  {
    DBUG_PRINT("info",("Sorting for send_fields"));
    thd->proc_info="Sorting result";
    /* If we have already done the group, add HAVING to sorted table */
1518 1519
    if (curr_join->tmp_having && ! curr_join->group_list && 
	! curr_join->sort_and_group)
unknown's avatar
unknown committed
1520
    {
1521 1522
      // Some tables may have been const
      curr_join->tmp_having->update_used_tables();
1523 1524 1525
      JOIN_TAB *curr_table= &curr_join->join_tab[curr_join->const_tables];
      table_map used_tables= (curr_join->const_table_map |
			      curr_table->table->map);
unknown's avatar
unknown committed
1526

1527 1528
      Item* sort_table_cond= make_cond_for_table(curr_join->tmp_having,
						 used_tables,
1529
						 used_tables);
unknown's avatar
unknown committed
1530 1531
      if (sort_table_cond)
      {
1532 1533
	if (!curr_table->select)
	  if (!(curr_table->select= new SQL_SELECT))
1534
	    DBUG_VOID_RETURN;
1535 1536
	if (!curr_table->select->cond)
	  curr_table->select->cond= sort_table_cond;
unknown's avatar
unknown committed
1537
	else					// This should never happen
unknown's avatar
af  
unknown committed
1538
	{
1539
	  if (!(curr_table->select->cond=
unknown's avatar
af  
unknown committed
1540 1541
		new Item_cond_and(curr_table->select->cond,
				  sort_table_cond)))
1542
	    DBUG_VOID_RETURN;
unknown's avatar
af  
unknown committed
1543 1544 1545 1546 1547 1548
	  /*
	    Item_cond_and do not need fix_fields for execution, its parameters
	    are fixed or do not need fix_fields, too
	  */
	  curr_table->select->cond->quick_fix_field();
	}
1549
	curr_table->select_cond= curr_table->select->cond;
1550 1551
	curr_table->select_cond->top_level_item();
	DBUG_EXECUTE("where",print_where(curr_table->select->cond,
unknown's avatar
unknown committed
1552
					 "select and having"););
1553 1554 1555
	curr_join->tmp_having= make_cond_for_table(curr_join->tmp_having,
						   ~ (table_map) 0,
						   ~used_tables);
unknown's avatar
unknown committed
1556 1557 1558
	DBUG_EXECUTE("where",print_where(conds,"having after sort"););
      }
    }
unknown's avatar
unknown committed
1559
    {
unknown's avatar
unknown committed
1560
      if (group)
1561
	curr_join->select_limit= HA_POS_ERROR;
unknown's avatar
unknown committed
1562
      else
unknown's avatar
unknown committed
1563
      {
unknown's avatar
unknown committed
1564 1565 1566 1567
	/*
	  We can abort sorting after thd->select_limit rows if we there is no
	  WHERE clause for any tables after the sorted one.
	*/
1568
	JOIN_TAB *curr_table= &curr_join->join_tab[curr_join->const_tables+1];
1569
	JOIN_TAB *end_table= &curr_join->join_tab[curr_join->tables];
1570
	for (; curr_table < end_table ; curr_table++)
unknown's avatar
unknown committed
1571
	{
unknown's avatar
unknown committed
1572 1573 1574 1575
	  /*
	    table->keyuse is set in the case there was an original WHERE clause
	    on the table that was optimized away.
	  */
1576
	  if (curr_table->select_cond ||
1577
	      (curr_table->keyuse && !curr_table->first_inner))
unknown's avatar
unknown committed
1578 1579
	  {
	    /* We have to sort all rows */
1580
	    curr_join->select_limit= HA_POS_ERROR;
unknown's avatar
unknown committed
1581 1582
	    break;
	  }
unknown's avatar
unknown committed
1583 1584
	}
      }
1585 1586 1587 1588
      if (curr_join->join_tab == join_tab && save_join_tab())
      {
	DBUG_VOID_RETURN;
      }
unknown's avatar
unknown committed
1589 1590 1591 1592 1593 1594 1595 1596 1597
      /*
	Here we sort rows for ORDER BY/GROUP BY clause, if the optimiser
	chose FILESORT to be faster than INDEX SCAN or there is no 
	suitable index present.
	Note, that create_sort_index calls test_if_skip_sort_order and may
	finally replace sorting with index scan if there is a LIMIT clause in
	the query. XXX: it's never shown in EXPLAIN!
	OPTION_FOUND_ROWS supersedes LIMIT and is taken into account.
      */
1598
      if (create_sort_index(thd, curr_join,
1599 1600
			    curr_join->group_list ? 
			    curr_join->group_list : curr_join->order,
unknown's avatar
unknown committed
1601 1602 1603
			    curr_join->select_limit,
			    (select_options & OPTION_FOUND_ROWS ?
			     HA_POS_ERROR : unit->select_limit_cnt)))
1604
	DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1605
    }
unknown's avatar
unknown committed
1606
  }
1607 1608 1609 1610 1611 1612
  /* XXX: When can we have here thd->net.report_error not zero? */
  if (thd->net.report_error)
  {
    error= thd->net.report_error;
    DBUG_VOID_RETURN;
  }
1613
  curr_join->having= curr_join->tmp_having;
1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640
  curr_join->fields= curr_fields_list;
  curr_join->procedure= procedure;

  if (unit == &thd->lex->unit &&
      (unit->fake_select_lex == 0 || select_lex == unit->fake_select_lex) &&
      thd->cursor && tables != const_tables)
  {
    /*
      We are here if this is JOIN::exec for the last select of the main unit
      and the client requested to open a cursor.
      We check that not all tables are constant because this case is not
      handled by do_select() separately, and this case is not implemented
      for cursors yet.
    */
    DBUG_ASSERT(error == 0);
    /*
      curr_join is used only for reusable joins - that is, 
      to perform SELECT for each outer row (like in subselects).
      This join is main, so we know for sure that curr_join == join.
    */
    DBUG_ASSERT(curr_join == this);
    /* Open cursor for the last join sweep */
    error= thd->cursor->open(this);
  }
  else
  {
    thd->proc_info="Sending data";
unknown's avatar
unknown committed
1641
    DBUG_PRINT("info", ("%s", thd->proc_info));
1642 1643
    result->send_fields(*curr_fields_list,
                        Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
1644 1645 1646 1647 1648
    error= do_select(curr_join, curr_fields_list, NULL, procedure);
    thd->limit_found_rows= curr_join->send_records;
    thd->examined_row_count= curr_join->examined_rows;
  }

1649 1650
  DBUG_VOID_RETURN;
}
unknown's avatar
unknown committed
1651

1652

1653 1654 1655 1656 1657
/*
  Clean up join. Return error that hold JOIN.
*/

int
1658
JOIN::cleanup()
1659
{
1660
  DBUG_ENTER("JOIN::cleanup");
1661 1662 1663
  select_lex->join= 0;

  if (tmp_join)
unknown's avatar
unknown committed
1664 1665 1666 1667 1668 1669
  {
    if (join_tab != tmp_join->join_tab)
    {
      JOIN_TAB *tab, *end;
      for (tab= join_tab, end= tab+tables ; tab != end ; tab++)
      {
unknown's avatar
af  
unknown committed
1670
	tab->cleanup();
unknown's avatar
unknown committed
1671 1672 1673
      }
    }
    tmp_join->tmp_join= 0;
unknown's avatar
unknown committed
1674
    tmp_table_param.copy_field=0;
1675
    DBUG_RETURN(tmp_join->cleanup());
unknown's avatar
unknown committed
1676
  }
unknown's avatar
unknown committed
1677
  cond_equal= 0;
1678

1679
  lock=0;                                     // It's faster to unlock later
1680
  join_free(1);
unknown's avatar
af  
unknown committed
1681 1682 1683 1684
  if (exec_tmp_table1)
    free_tmp_table(thd, exec_tmp_table1);
  if (exec_tmp_table2)
    free_tmp_table(thd, exec_tmp_table2);
unknown's avatar
unknown committed
1685 1686 1687
  delete select;
  delete_dynamic(&keyuse);
  delete procedure;
1688 1689 1690
  for (SELECT_LEX_UNIT *lex_unit= select_lex->first_inner_unit();
       lex_unit != 0;
       lex_unit= lex_unit->next_unit())
1691
  {
1692
    error|= lex_unit->cleanup();
1693 1694
  }
  DBUG_RETURN(error);
1695 1696
}

1697

1698 1699 1700 1701 1702 1703 1704 1705
/************************* Cursor ******************************************/
  
void
Cursor::init_from_thd(THD *thd)
{
  /*
    We need to save and reset thd->mem_root, otherwise it'll be freed
    later in mysql_parse.
unknown's avatar
unknown committed
1706 1707 1708

    We can't just change the thd->mem_root here as we want to keep the things
    that is already allocated in thd->mem_root for Cursor::fetch()
1709
  */
unknown's avatar
unknown committed
1710 1711 1712
  main_mem_root=  *thd->mem_root;
  /* Allocate new memory root for thd */
  init_sql_alloc(thd->mem_root,
1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725
                 thd->variables.query_alloc_block_size,
                 thd->variables.query_prealloc_size);

  /*
    The same is true for open tables and lock: save tables and zero THD
    pointers to prevent table close in close_thread_tables (This is a part
    of the temporary solution to make cursors work with minimal changes to
    the current source base).
  */
  derived_tables= thd->derived_tables;
  open_tables=    thd->open_tables;
  lock=           thd->lock;
  query_id=       thd->query_id;
unknown's avatar
unknown committed
1726
  free_list=	  thd->free_list;
1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769
  reset_thd(thd);
  /*
    XXX: thd->locked_tables is not changed.
    What problems can we have with it if cursor is open?
  */
  /*
    TODO: grab thd->free_list here?
  */
}


void
Cursor::init_thd(THD *thd)
{
  DBUG_ASSERT(thd->derived_tables == 0);
  thd->derived_tables= derived_tables;

  DBUG_ASSERT(thd->open_tables == 0);
  thd->open_tables= open_tables;

  DBUG_ASSERT(thd->lock== 0);
  thd->lock= lock;
  thd->query_id= query_id;
}


void
Cursor::reset_thd(THD *thd)
{
  thd->derived_tables= 0;
  thd->open_tables= 0;
  thd->lock= 0;
  thd->free_list= 0;
}


int
Cursor::open(JOIN *join_arg)
{
  join= join_arg;
  THD *thd= join->thd;
  /* First non-constant table */
  JOIN_TAB *join_tab= join->join_tab + join->const_tables;
unknown's avatar
unknown committed
1770
  DBUG_ENTER("Cursor::open");
1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781

  /*
    Send fields description to the client; server_status is sent
    in 'EOF' packet, which ends send_fields().
  */
  thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
  join->result->send_fields(*join->fields, Protocol::SEND_NUM_ROWS);
  ::send_eof(thd);
  thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;

  /* Prepare JOIN for reading rows. */
unknown's avatar
unknown committed
1782
  join->tmp_table= 0;
1783
  join->join_tab[join->tables-1].next_select= setup_end_select_func(join);
1784 1785 1786 1787
  join->send_records= 0;
  join->fetch_limit= join->unit->offset_limit_cnt;

  /* Disable JOIN CACHE as it is not working with cursors yet */
unknown's avatar
unknown committed
1788 1789 1790
  for (JOIN_TAB *tab= join_tab;
       tab != join->join_tab + join->tables - 1;
       tab++)
1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803
  {
    if (tab->next_select == sub_select_cache)
      tab->next_select= sub_select;
  }

  DBUG_ASSERT(join_tab->table->reginfo.not_exists_optimize == 0);
  DBUG_ASSERT(join_tab->not_used_in_distinct == 0);
  /*
    null_row is set only if row not found and it's outer join: should never
    happen for the first table in join_tab list
  */
  DBUG_ASSERT(join_tab->table->null_row == 0);

1804 1805 1806 1807 1808
  /*
    There is always at least one record in the table, as otherwise we
    wouldn't have opened the cursor. Therefore a failure is the only
    reason read_first_record can return not 0.
  */
unknown's avatar
unknown committed
1809
  DBUG_RETURN(join_tab->read_first_record(join_tab));
1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827
}


/*
  DESCRIPTION
    Fetch next num_rows rows from the cursor and sent them to the client
  PRECONDITION:
    Cursor is open
  RETURN VALUES:
    -4  there are more rows, send_eof sent to the client
     0  no more rows, send_eof was sent to the client, cursor is closed
 other  fatal fetch error, cursor is closed (error is not reported)
*/

int
Cursor::fetch(ulong num_rows)
{
  THD *thd= join->thd;
unknown's avatar
unknown committed
1828
  JOIN_TAB *join_tab= join->join_tab + join->const_tables;
unknown's avatar
unknown committed
1829
  COND *on_expr= *join_tab->on_expr_ref;
1830 1831 1832 1833
  COND *select_cond= join_tab->select_cond;
  READ_RECORD *info= &join_tab->read_record;
  int error= 0;

1834 1835
  /* save references to memory, allocated during fetch */
  thd->set_n_backup_item_arena(this, &thd->stmt_backup);
unknown's avatar
unknown committed
1836

1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851
  join->fetch_limit+= num_rows;

  /*
    Run while there are new rows in the first table;
    For each row, satisfying ON and WHERE clauses (those parts of them which
    can be evaluated early), call next_select.
  */
  do
  {
    int no_more_rows;

    join->examined_rows++;

    if (thd->killed)                            /* Aborted by user */
    {
unknown's avatar
unknown committed
1852
      my_message(ER_SERVER_SHUTDOWN, ER(ER_SERVER_SHUTDOWN), MYF(0));
1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900
      return -1;
    }

    if (on_expr == 0 || on_expr->val_int())
    {
      if (select_cond == 0 || select_cond->val_int())
      {
        /*
          TODO: call table->unlock_row() to unlock row failed selection,
          when this feature will be used.
        */
        error= join_tab->next_select(join, join_tab + 1, 0);
        DBUG_ASSERT(error <= 0);
        if (error)
        {
          /* real error or LIMIT/FETCH LIMIT worked */
          if (error == -4)
          {
            /*
              FETCH LIMIT, read ahead one row, and close cursor
              if there is no more rows XXX: to be fixed to support
              non-equi-joins!
            */
            if ((no_more_rows= info->read_record(info)))
              error= no_more_rows > 0 ? -1: 0;
          }
          break;
        }
      }
    }
    /* read next row; break loop if there was an error */
    if ((no_more_rows= info->read_record(info)))
    {
      if (no_more_rows > 0)
        error= -1;
      else
      {
        enum { END_OF_RECORDS= 1 };
        error= join_tab->next_select(join, join_tab+1, (int) END_OF_RECORDS);
      }
      break;
    }
  }
  while (thd->net.report_error == 0);

  if (thd->net.report_error)
    error= -1;

1901 1902
  if (error == -3)                              /* LIMIT clause worked */
    error= 0;
1903

1904
#ifdef USING_TRANSACTIONS
unknown's avatar
unknown committed
1905
    ha_release_temporary_latches(thd);
1906 1907 1908 1909 1910 1911
#endif

  thd->restore_backup_item_arena(this, &thd->stmt_backup);
  if (error == -4)
  {
    /* Fetch limit worked, possibly more rows are there */
1912 1913 1914
    thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
    ::send_eof(thd);
    thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
1915 1916 1917
  }
  else
  {
1918
    close();
1919 1920 1921 1922 1923 1924 1925
    if (error == 0)
    {
      thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
      ::send_eof(thd);
      thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
    }
    else
1926
      my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
1927 1928 1929
    /* free cursor memory */
    free_items(free_list);
    free_list= 0;
unknown's avatar
unknown committed
1930
    free_root(&main_mem_root, MYF(0));
1931 1932 1933 1934 1935 1936 1937 1938 1939
  }
  return error;
}


void
Cursor::close()
{
  THD *thd= join->thd;
unknown's avatar
unknown committed
1940 1941
  DBUG_ENTER("Cursor::close");

1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968
  join->join_free(0);
  if (unit)
  {
    /* In case of UNIONs JOIN is freed inside unit->cleanup() */
    unit->cleanup();
  }
  else
  {
    join->cleanup();
    delete join;
  }
  /* XXX: Another hack: closing tables used in the cursor */
  {
    DBUG_ASSERT(lock || open_tables || derived_tables);

    TABLE *tmp_derived_tables= thd->derived_tables;
    MYSQL_LOCK *tmp_lock= thd->lock;

    thd->open_tables= open_tables;
    thd->derived_tables= derived_tables;
    thd->lock= lock;
    close_thread_tables(thd);

    thd->open_tables= tmp_derived_tables;
    thd->derived_tables= tmp_derived_tables;
    thd->lock= tmp_lock;
  }
1969 1970
  join= 0;
  unit= 0;
unknown's avatar
unknown committed
1971
  DBUG_VOID_RETURN;
1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983
}


Cursor::~Cursor()
{
  if (is_open())
    close();
  free_items(free_list);
  /*
    Must be last, as some memory might be allocated for free purposes,
    like in free_tmp_table() (TODO: fix this issue)
  */
unknown's avatar
unknown committed
1984
  free_root(&main_mem_root, MYF(0));
1985 1986 1987 1988 1989
}

/*********************************************************************/


unknown's avatar
unknown committed
1990
bool
1991
mysql_select(THD *thd, Item ***rref_pointer_array,
unknown's avatar
unknown committed
1992
	     TABLE_LIST *tables, uint wild_num, List<Item> &fields,
1993 1994 1995
	     COND *conds, uint og_num,  ORDER *order, ORDER *group,
	     Item *having, ORDER *proc_param, ulong select_options,
	     select_result *result, SELECT_LEX_UNIT *unit,
1996
	     SELECT_LEX *select_lex)
1997
{
unknown's avatar
unknown committed
1998
  bool err;
unknown's avatar
unknown committed
1999
  bool free_join= 1;
2000 2001
  DBUG_ENTER("mysql_select");

unknown's avatar
unknown committed
2002
  JOIN *join;
2003
  if (select_lex->join != 0)
2004
  {
unknown's avatar
unknown committed
2005
    join= select_lex->join;
unknown's avatar
unknown committed
2006 2007 2008 2009
    /*
      is it single SELECT in derived table, called in derived table
      creation
    */
2010 2011
    if (select_lex->linkage != DERIVED_TABLE_TYPE ||
	(select_options & SELECT_DESCRIBE))
unknown's avatar
unknown committed
2012
    {
2013
      if (select_lex->linkage != GLOBAL_OPTIONS_TYPE)
2014
      {
2015
	//here is EXPLAIN of subselect or derived table
unknown's avatar
af  
unknown committed
2016
	if (join->change_result(result))
2017
	{
unknown's avatar
unknown committed
2018
	  DBUG_RETURN(TRUE);
2019
	}
2020
      }
2021
      else
2022
      {
2023 2024 2025 2026 2027 2028
	if (join->prepare(rref_pointer_array, tables, wild_num,
			  conds, og_num, order, group, having, proc_param,
			  select_lex, unit))
	{
	  goto err;
	}
2029
      }
unknown's avatar
unknown committed
2030
    }
unknown's avatar
af  
unknown committed
2031
    free_join= 0;
unknown's avatar
unknown committed
2032
    join->select_options= select_options;
2033
  }
unknown's avatar
unknown committed
2034 2035
  else
  {
unknown's avatar
af  
unknown committed
2036
    if (!(join= new JOIN(thd, fields, select_options, result)))
unknown's avatar
unknown committed
2037
	DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
2038 2039
    thd->proc_info="init";
    thd->used_tables=0;                         // Updated by setup_fields
2040 2041
    if (join->prepare(rref_pointer_array, tables, wild_num,
		      conds, og_num, order, group, having, proc_param,
2042
		      select_lex, unit))
unknown's avatar
unknown committed
2043
    {
2044
      goto err;
unknown's avatar
unknown committed
2045 2046 2047
    }
  }

unknown's avatar
unknown committed
2048
  if ((err= join->optimize()))
unknown's avatar
unknown committed
2049
  {
unknown's avatar
unknown committed
2050 2051
    goto err;					// 1
  }
2052

unknown's avatar
unknown committed
2053
  if (thd->lex->describe & DESCRIBE_EXTENDED)
unknown's avatar
unknown committed
2054 2055 2056 2057 2058
  {
    join->conds_history= join->conds;
    join->having_history= (join->having?join->having:join->tmp_having);
  }

2059
  if (thd->net.report_error)
2060 2061 2062 2063
    goto err;

  join->exec();

2064 2065 2066 2067 2068 2069 2070 2071 2072 2073
  if (thd->cursor && thd->cursor->is_open())
  {
    /*
      A cursor was opened for the last sweep in exec().
      We are here only if this is mysql_select for top-level SELECT_LEX_UNIT
      and there were no error.
    */
    free_join= 0;
  }

unknown's avatar
unknown committed
2074
  if (thd->lex->describe & DESCRIBE_EXTENDED)
unknown's avatar
unknown committed
2075 2076 2077 2078 2079
  {
    select_lex->where= join->conds_history;
    select_lex->having= join->having_history;
  }

2080
err:
unknown's avatar
unknown committed
2081 2082 2083
  if (free_join)
  {
    thd->proc_info="end";
2084
    err= join->cleanup();
unknown's avatar
unknown committed
2085
    delete join;
unknown's avatar
unknown committed
2086
    DBUG_RETURN(err || thd->net.report_error);
unknown's avatar
unknown committed
2087
  }
unknown's avatar
unknown committed
2088
  DBUG_RETURN(join->error);
unknown's avatar
unknown committed
2089 2090 2091
}

/*****************************************************************************
2092 2093
  Create JOIN_TABS, make a guess about the table types,
  Approximate how many records will be used in each table
unknown's avatar
unknown committed
2094 2095
*****************************************************************************/

2096 2097
static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
				      TABLE *table,
unknown's avatar
unknown committed
2098
				      const key_map *keys,ha_rows limit)
unknown's avatar
unknown committed
2099 2100 2101 2102 2103 2104 2105
{
  int error;
  DBUG_ENTER("get_quick_record_count");
  if (select)
  {
    select->head=table;
    table->reginfo.impossible_range=0;
unknown's avatar
af  
unknown committed
2106 2107
    if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,
					 limit)) == 1)
unknown's avatar
unknown committed
2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119
      DBUG_RETURN(select->quick->records);
    if (error == -1)
    {
      table->reginfo.impossible_range=1;
      DBUG_RETURN(0);
    }
    DBUG_PRINT("warning",("Couldn't use record count on const keypart"));
  }
  DBUG_RETURN(HA_POS_ERROR);			/* This shouldn't happend */
}


2120 2121 2122 2123 2124 2125 2126
/*
  Calculate the best possible join and initialize the join structure

  RETURN VALUES
  0	ok
  1	Fatal error
*/
unknown's avatar
unknown committed
2127

unknown's avatar
unknown committed
2128
static bool
2129
make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
2130
		     DYNAMIC_ARRAY *keyuse_array)
unknown's avatar
unknown committed
2131 2132
{
  int error;
2133
  TABLE *table;
2134 2135 2136
  uint i,table_count,const_count,key;
  table_map found_const_table_map, all_table_map, found_ref, refs;
  key_map const_ref, eq_part;
unknown's avatar
unknown committed
2137 2138 2139 2140 2141 2142 2143 2144
  TABLE **table_vector;
  JOIN_TAB *stat,*stat_end,*s,**stat_ref;
  KEYUSE *keyuse,*start_keyuse;
  table_map outer_join=0;
  JOIN_TAB *stat_vector[MAX_TABLES+1];
  DBUG_ENTER("make_join_statistics");

  table_count=join->tables;
2145 2146
  stat=(JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB)*table_count);
  stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)*MAX_TABLES);
2147
  table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*(table_count*2));
unknown's avatar
unknown committed
2148 2149 2150 2151 2152 2153
  if (!stat || !stat_ref || !table_vector)
    DBUG_RETURN(1);				// Eom /* purecov: inspected */

  join->best_ref=stat_vector;

  stat_end=stat+table_count;
2154
  found_const_table_map= all_table_map=0;
unknown's avatar
unknown committed
2155 2156
  const_count=0;

unknown's avatar
VIEW  
unknown committed
2157 2158
  for (s= stat, i= 0;
       tables;
2159
       s++, tables= tables->next_leaf, i++)
unknown's avatar
unknown committed
2160
  {
2161
    TABLE_LIST *embedding= tables->embedding;
unknown's avatar
unknown committed
2162
    stat_vector[i]=s;
2163 2164 2165 2166
    s->keys.init();
    s->const_keys.init();
    s->checked_keys.init();
    s->needed_reg.init();
unknown's avatar
unknown committed
2167
    table_vector[i]=s->table=table=tables->table;
2168
    table->pos_in_table_list= tables;
unknown's avatar
unknown committed
2169
    table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);// record count
2170
    table->quick_keys.clear_all();
unknown's avatar
unknown committed
2171 2172
    table->reginfo.join_tab=s;
    table->reginfo.not_exists_optimize=0;
2173
    bzero((char*) table->const_key_parts, sizeof(key_part_map)*table->s->keys);
unknown's avatar
unknown committed
2174
    all_table_map|= table->map;
2175
    s->join=join;
2176
    s->info=0;					// For describe
2177 2178 2179

    s->dependent= tables->dep_tables;
    s->key_dependent= 0;
2180 2181
    if (tables->schema_table)
      table->file->records= 2;
2182

unknown's avatar
unknown committed
2183 2184
    s->on_expr_ref= &tables->on_expr;
    if (*s->on_expr_ref)
unknown's avatar
unknown committed
2185
    {
2186
      /* s is the only inner table of an outer join */
unknown's avatar
unknown committed
2187 2188
      if (!table->file->records)
      {						// Empty table
2189
        s->dependent= 0;                        // Ignore LEFT JOIN depend.
unknown's avatar
unknown committed
2190 2191 2192
	set_position(join,const_count++,s,(KEYUSE*) 0);
	continue;
      }
2193
      outer_join|= table->map;
unknown's avatar
unknown committed
2194 2195
      continue;
    }
2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209
    if (embedding)
    {
      /* s belongs to a nested join, maybe to several embedded joins */
      do
      {
        NESTED_JOIN *nested_join= embedding->nested_join;
        s->dependent|= embedding->dep_tables;
        embedding= embedding->embedding;
        outer_join|= nested_join->used_tables;
      }
      while (embedding);
      continue;
    }

2210
    if ((table->s->system || table->file->records <= 1) && ! s->dependent &&
2211
	!(table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
unknown's avatar
unknown committed
2212
        !table->fulltext_searched)
unknown's avatar
unknown committed
2213 2214 2215 2216 2217
    {
      set_position(join,const_count++,s,(KEYUSE*) 0);
    }
  }
  stat_vector[i]=0;
2218
  join->outer_join=outer_join;
unknown's avatar
unknown committed
2219

2220
  if (join->outer_join)
unknown's avatar
unknown committed
2221
  {
2222 2223 2224 2225 2226 2227
    /* 
       Build transitive closure for relation 'to be dependent on'.
       This will speed up the plan search for many cases with outer joins,
       as well as allow us to catch illegal cross references/
       Warshall's algorithm is used to build the transitive closure.
       As we use bitmaps to represent the relation the complexity
unknown's avatar
unknown committed
2228
       of the algorithm is O((number of tables)^2). 
2229 2230
    */
    for (i= 0, s= stat ; i < table_count ; i++, s++)
unknown's avatar
unknown committed
2231
    {
2232
      for (uint j= 0 ; j < table_count ; j++)
unknown's avatar
unknown committed
2233
      {
2234 2235 2236 2237
        table= stat[j].table;
        if (s->dependent & table->map)
          s->dependent |= table->reginfo.join_tab->dependent;
      }
unknown's avatar
unknown committed
2238 2239
      if (s->dependent)
        s->table->maybe_null= 1;
2240 2241 2242 2243 2244 2245 2246
    }
    /* Catch illegal cross references for outer joins */
    for (i= 0, s= stat ; i < table_count ; i++, s++)
    {
      if (s->dependent & s->table->map)
      {
        join->tables=0;			// Don't use join->table
unknown's avatar
unknown committed
2247
        my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0));
2248
        DBUG_RETURN(1);
unknown's avatar
unknown committed
2249
      }
2250
      s->key_dependent= s->dependent;
unknown's avatar
unknown committed
2251 2252 2253 2254
    }
  }

  if (conds || outer_join)
2255
    if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables,
unknown's avatar
unknown committed
2256 2257
                            conds, join->cond_equal,
                            ~outer_join, join->select_lex))
unknown's avatar
unknown committed
2258 2259
      DBUG_RETURN(1);

2260
  /* Read tables with 0 or 1 rows (system tables) */
2261
  join->const_table_map= 0;
2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279

  for (POSITION *p_pos=join->positions, *p_end=p_pos+const_count;
       p_pos < p_end ;
       p_pos++)
  {
    int tmp;
    s= p_pos->table;
    s->type=JT_SYSTEM;
    join->const_table_map|=s->table->map;
    if ((tmp=join_read_const_table(s, p_pos)))
    {
      if (tmp > 0)
	DBUG_RETURN(1);			// Fatal error
    }
    else
      found_const_table_map|= s->table->map;
  }

unknown's avatar
unknown committed
2280
  /* loop until no more const tables are found */
2281
  int ref_changed;
unknown's avatar
unknown committed
2282 2283
  do
  {
2284
    ref_changed = 0;
unknown's avatar
unknown committed
2285
    found_ref=0;
2286 2287 2288 2289 2290 2291 2292

    /*
      We only have to loop from stat_vector + const_count as
      set_position() will move all const_tables first in stat_vector
    */

    for (JOIN_TAB **pos=stat_vector+const_count ; (s= *pos) ; pos++)
unknown's avatar
unknown committed
2293
    {
2294
      table=s->table;
unknown's avatar
unknown committed
2295 2296
      if (s->dependent)				// If dependent on some table
      {
2297
	// All dep. must be constants
2298
	if (s->dependent & ~(found_const_table_map))
unknown's avatar
unknown committed
2299
	  continue;
2300
	if (table->file->records <= 1L &&
2301 2302
	    !(table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
            !table->pos_in_table_list->embedding)
unknown's avatar
unknown committed
2303
	{					// system table
2304
	  int tmp= 0;
unknown's avatar
unknown committed
2305
	  s->type=JT_SYSTEM;
2306
	  join->const_table_map|=table->map;
unknown's avatar
unknown committed
2307
	  set_position(join,const_count++,s,(KEYUSE*) 0);
2308
	  if ((tmp= join_read_const_table(s,join->positions+const_count-1)))
2309 2310 2311 2312 2313 2314
	  {
	    if (tmp > 0)
	      DBUG_RETURN(1);			// Fatal error
	  }
	  else
	    found_const_table_map|= table->map;
unknown's avatar
unknown committed
2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325
	  continue;
	}
      }
      /* check if table can be read by key or table only uses const refs */
      if ((keyuse=s->keyuse))
      {
	s->type= JT_REF;
	while (keyuse->table == table)
	{
	  start_keyuse=keyuse;
	  key=keyuse->key;
2326
	  s->keys.set_bit(key);               // QQ: remove this ?
unknown's avatar
unknown committed
2327

2328 2329 2330
	  refs=0;
          const_ref.clear_all();
	  eq_part.clear_all();
unknown's avatar
unknown committed
2331 2332
	  do
	  {
2333
	    if (keyuse->val->type() != Item::NULL_ITEM && !keyuse->optimize)
unknown's avatar
unknown committed
2334
	    {
2335
	      if (!((~found_const_table_map) & keyuse->used_tables))
2336
		const_ref.set_bit(keyuse->keypart);
unknown's avatar
unknown committed
2337 2338
	      else
		refs|=keyuse->used_tables;
2339
	      eq_part.set_bit(keyuse->keypart);
unknown's avatar
unknown committed
2340 2341 2342 2343
	    }
	    keyuse++;
	  } while (keyuse->table == table && keyuse->key == key);

2344
	  if (eq_part.is_prefix(table->key_info[key].key_parts) &&
2345 2346
	      ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
	       HA_NOSAME) &&
unknown's avatar
unknown committed
2347
              !table->fulltext_searched)
unknown's avatar
unknown committed
2348 2349 2350
	  {
	    if (const_ref == eq_part)
	    {					// Found everything for ref.
2351 2352
	      int tmp;
	      ref_changed = 1;
2353
	      s->type= JT_CONST;
2354
	      join->const_table_map|=table->map;
unknown's avatar
unknown committed
2355
	      set_position(join,const_count++,s,start_keyuse);
2356
	      if (create_ref_for_key(join, s, start_keyuse,
2357
				     found_const_table_map))
2358 2359 2360 2361 2362 2363 2364 2365 2366
		DBUG_RETURN(1);
	      if ((tmp=join_read_const_table(s,
					     join->positions+const_count-1)))
	      {
		if (tmp > 0)
		  DBUG_RETURN(1);			// Fatal error
	      }
	      else
		found_const_table_map|= table->map;
unknown's avatar
unknown committed
2367 2368 2369 2370 2371 2372 2373 2374
	      break;
	    }
	    else
	      found_ref|= refs;		// Table is const if all refs are const
	  }
	}
      }
    }
2375
  } while (join->const_table_map & found_ref && ref_changed);
unknown's avatar
unknown committed
2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388

  /* Calc how many (possible) matched records in each table */

  for (s=stat ; s < stat_end ; s++)
  {
    if (s->type == JT_SYSTEM || s->type == JT_CONST)
    {
      /* Only one matching row */
      s->found_records=s->records=s->read_time=1; s->worst_seeks=1.0;
      continue;
    }
    /* Approximate found rows and time to read them */
    s->found_records=s->records=s->table->file->records;
2389
    s->read_time=(ha_rows) s->table->file->scan_time();
unknown's avatar
unknown committed
2390

2391 2392
    /*
      Set a max range of how many seeks we can expect when using keys
2393 2394
      This is can't be to high as otherwise we are likely to use
      table scan.
2395
    */
2396 2397
    s->worst_seeks= min((double) s->found_records / 10,
			(double) s->read_time*3);
unknown's avatar
unknown committed
2398 2399 2400
    if (s->worst_seeks < 2.0)			// Fix for small tables
      s->worst_seeks=2.0;

2401 2402 2403 2404 2405 2406
    /*
      Add to stat->const_keys those indexes for which all group fields or
      all select distinct fields participate in one index.
    */
    add_group_and_distinct_keys(join, s);

2407 2408
    if (!s->const_keys.is_clear_all() &&
        !s->table->pos_in_table_list->embedding)
unknown's avatar
unknown committed
2409 2410
    {
      ha_rows records;
2411 2412 2413
      SQL_SELECT *select;
      select= make_select(s->table, found_const_table_map,
			  found_const_table_map,
unknown's avatar
unknown committed
2414
			  *s->on_expr_ref ? *s->on_expr_ref : conds,
unknown's avatar
unknown committed
2415
			  1, &error);
2416 2417
      if (!select)
        DBUG_RETURN(1);
2418
      records= get_quick_record_count(join->thd, select, s->table,
unknown's avatar
unknown committed
2419
				      &s->const_keys, join->row_limit);
unknown's avatar
unknown committed
2420 2421 2422
      s->quick=select->quick;
      s->needed_reg=select->needed_reg;
      select->quick=0;
2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433
      if (records == 0 && s->table->reginfo.impossible_range)
      {
	/*
	  Impossible WHERE or ON expression
	  In case of ON, we mark that the we match one empty NULL row.
	  In case of WHERE, don't set found_const_table_map to get the
	  caller to abort with a zero row result.
	*/
	join->const_table_map|= s->table->map;
	set_position(join,const_count++,s,(KEYUSE*) 0);
	s->type= JT_CONST;
unknown's avatar
unknown committed
2434
	if (*s->on_expr_ref)
2435 2436 2437 2438 2439 2440 2441 2442
	{
	  /* Generate empty row */
	  s->info= "Impossible ON condition";
	  found_const_table_map|= s->table->map;
	  s->type= JT_CONST;
	  mark_as_null_row(s->table);		// All fields are NULL
	}
      }
unknown's avatar
unknown committed
2443 2444
      if (records != HA_POS_ERROR)
      {
2445
	s->found_records=records;
unknown's avatar
unknown committed
2446 2447
	s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
      }
2448
      delete select;
unknown's avatar
unknown committed
2449 2450 2451 2452 2453 2454 2455
    }
  }

  join->join_tab=stat;
  join->map2table=stat_ref;
  join->table= join->all_tables=table_vector;
  join->const_tables=const_count;
2456
  join->found_const_table_map=found_const_table_map;
unknown's avatar
unknown committed
2457

2458
  /* Find an optimal join order of the non-constant tables. */
unknown's avatar
unknown committed
2459
  if (join->const_tables != join->tables)
2460 2461
  {
    optimize_keyuse(join, keyuse_array);
unknown's avatar
af  
unknown committed
2462
    choose_plan(join, all_table_map & ~join->const_table_map);
2463
  }
unknown's avatar
unknown committed
2464 2465 2466 2467 2468 2469
  else
  {
    memcpy((gptr) join->best_positions,(gptr) join->positions,
	   sizeof(POSITION)*join->const_tables);
    join->best_read=1.0;
  }
2470
  /* Generate an execution plan from the found optimal join order. */
unknown's avatar
unknown committed
2471
  DBUG_RETURN(join->thd->killed || get_best_combination(join));
unknown's avatar
unknown committed
2472 2473 2474 2475
}


/*****************************************************************************
2476 2477 2478 2479 2480
  Check with keys are used and with tables references with tables
  Updates in stat:
	  keys	     Bitmap of all used keys
	  const_keys Bitmap of all keys with may be used with quick_select
	  keyuse     Pointer to possible keys
unknown's avatar
unknown committed
2481 2482 2483 2484 2485
*****************************************************************************/

typedef struct key_field_t {		// Used when finding key fields
  Field		*field;
  Item		*val;			// May be empty if diff constant
2486 2487
  uint		level;
  uint		optimize;
unknown's avatar
unknown committed
2488
  bool		eq_func;
2489 2490 2491 2492 2493
  /*
    If true, the condition this struct represents will not be satisfied
    when val IS NULL.
  */
  bool          null_rejecting; 
unknown's avatar
unknown committed
2494 2495
} KEY_FIELD;

2496 2497 2498 2499 2500 2501 2502 2503
/* Values in optimize */
#define KEY_OPTIMIZE_EXISTS		1
#define KEY_OPTIMIZE_REF_OR_NULL	2

/*
  Merge new key definitions to old ones, remove those not used in both

  This is called for OR between different levels
unknown's avatar
unknown committed
2504

2505 2506 2507 2508 2509
  To be able to do 'ref_or_null' we merge a comparison of a column
  and 'column IS NULL' to one test.  This is useful for sub select queries
  that are internally transformed to something like:

  SELECT * FROM t1 WHERE t1.key=outer_ref_field or t1.key IS NULL 
2510 2511 2512 2513 2514 2515

  KEY_FIELD::null_rejecting is processed as follows:
  result has null_rejecting=true if it is set for both ORed references.
  for example:
    (t2.key = t1.field OR t2.key  =  t1.field) -> null_rejecting=true
    (t2.key = t1.field OR t2.key <=> t1.field) -> null_rejecting=false
2516
*/
unknown's avatar
unknown committed
2517 2518 2519 2520 2521 2522 2523 2524

static KEY_FIELD *
merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
		 uint and_level)
{
  if (start == new_fields)
    return start;				// Impossible or
  if (new_fields == end)
unknown's avatar
unknown committed
2525
    return start;				// No new fields, skip all
unknown's avatar
unknown committed
2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537

  KEY_FIELD *first_free=new_fields;

  /* Mark all found fields in old array */
  for (; new_fields != end ; new_fields++)
  {
    for (KEY_FIELD *old=start ; old != first_free ; old++)
    {
      if (old->field == new_fields->field)
      {
	if (new_fields->val->used_tables())
	{
2538 2539 2540 2541
	  /*
	    If the value matches, we can use the key reference.
	    If not, we keep it until we have examined all new values
	  */
2542
	  if (old->val->eq(new_fields->val, old->field->binary()))
unknown's avatar
unknown committed
2543
	  {
2544 2545 2546 2547 2548
	    old->level= and_level;
	    old->optimize= ((old->optimize & new_fields->optimize &
			     KEY_OPTIMIZE_EXISTS) |
			    ((old->optimize | new_fields->optimize) &
			     KEY_OPTIMIZE_REF_OR_NULL));
2549 2550
            old->null_rejecting= old->null_rejecting && 
                                 new_fields->null_rejecting;
unknown's avatar
unknown committed
2551 2552
	  }
	}
2553 2554
	else if (old->eq_func && new_fields->eq_func &&
		 old->val->eq(new_fields->val, old->field->binary()))
2555

2556 2557 2558 2559 2560 2561
	{
	  old->level= and_level;
	  old->optimize= ((old->optimize & new_fields->optimize &
			   KEY_OPTIMIZE_EXISTS) |
			  ((old->optimize | new_fields->optimize) &
			   KEY_OPTIMIZE_REF_OR_NULL));
2562 2563
          old->null_rejecting= old->null_rejecting && 
                               new_fields->null_rejecting;
2564 2565 2566
	}
	else if (old->eq_func && new_fields->eq_func &&
		 (old->val->is_null() || new_fields->val->is_null()))
unknown's avatar
unknown committed
2567
	{
2568 2569 2570 2571 2572 2573
	  /* field = expression OR field IS NULL */
	  old->level= and_level;
	  old->optimize= KEY_OPTIMIZE_REF_OR_NULL;
	  /* Remember the NOT NULL value */
	  if (old->val->is_null())
	    old->val= new_fields->val;
2574 2575
          /* The referred expression can be NULL: */ 
          old->null_rejecting= false;
unknown's avatar
unknown committed
2576
	}
2577
	else
unknown's avatar
unknown committed
2578
	{
2579 2580 2581 2582 2583
	  /*
	    We are comparing two different const.  In this case we can't
	    use a key-lookup on this so it's better to remove the value
	    and let the range optimzier handle it
	  */
unknown's avatar
unknown committed
2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594
	  if (old == --first_free)		// If last item
	    break;
	  *old= *first_free;			// Remove old value
	  old--;				// Retry this value
	}
      }
    }
  }
  /* Remove all not used items */
  for (KEY_FIELD *old=start ; old != first_free ;)
  {
2595
    if (old->level != and_level)
unknown's avatar
unknown committed
2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607
    {						// Not used in all levels
      if (old == --first_free)
	break;
      *old= *first_free;			// Remove old value
      continue;
    }
    old++;
  }
  return first_free;
}


2608 2609 2610 2611 2612 2613 2614
/*
  Add a possible key to array of possible keys if it's usable as a key

  SYNPOSIS
    add_key_field()
    key_fields			Pointer to add key, if usable
    and_level			And level, to be stored in KEY_FIELD
2615
    cond                        Condition predicate
2616 2617 2618
    field			Field used in comparision
    eq_func			True if we used =, <=> or IS NULL
    value			Value used for comparison with field
2619
                                Is NULL for BETWEEN and IN
2620 2621 2622 2623 2624 2625 2626 2627 2628 2629
    usable_tables		Tables which can be used for key optimization

  NOTES
    If we are doing a NOT NULL comparison on a NOT NULL field in a outer join
    table, we store this to be able to do not exists optimization later.

  RETURN
    *key_fields is incremented if we stored a key in the array
*/

unknown's avatar
unknown committed
2630
static void
2631
add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
2632
	      Field *field, bool eq_func, Item **value, uint num_values,
unknown's avatar
unknown committed
2633 2634
	      table_map usable_tables)
{
2635
  uint exists_optimize= 0;
unknown's avatar
unknown committed
2636 2637 2638
  if (!(field->flags & PART_KEY_FLAG))
  {
    // Don't remove column IS NULL on a LEFT JOIN table
2639 2640
    if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
        !field->table->maybe_null || field->null_ptr)
unknown's avatar
unknown committed
2641
      return;					// Not a key. Skip it
2642
    exists_optimize= KEY_OPTIMIZE_EXISTS;
unknown's avatar
unknown committed
2643 2644 2645 2646
  }
  else
  {
    table_map used_tables=0;
2647 2648 2649
    bool optimizable=0;
    for (uint i=0; i<num_values; i++)
    {
unknown's avatar
af  
unknown committed
2650 2651
      used_tables|=(value[i])->used_tables();
      if (!((value[i])->used_tables() & (field->table->map | RAND_TABLE_BIT)))
2652 2653 2654
        optimizable=1;
    }
    if (!optimizable)
unknown's avatar
unknown committed
2655 2656 2657
      return;
    if (!(usable_tables & field->table->map))
    {
2658 2659
      if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
          !field->table->maybe_null || field->null_ptr)
unknown's avatar
unknown committed
2660
	return;					// Can't use left join optimize
2661
      exists_optimize= KEY_OPTIMIZE_EXISTS;
unknown's avatar
unknown committed
2662 2663 2664 2665
    }
    else
    {
      JOIN_TAB *stat=field->table->reginfo.join_tab;
unknown's avatar
unknown committed
2666
      key_map possible_keys=field->key_start;
2667 2668
      possible_keys.intersect(field->table->keys_in_use_for_query);
      stat[0].keys.merge(possible_keys);             // Add possible keys
unknown's avatar
unknown committed
2669

2670 2671 2672 2673 2674 2675 2676 2677
      /*
	Save the following cases:
	Field op constant
	Field LIKE constant where constant doesn't start with a wildcard
	Field = field2 where field2 is in a different table
	Field op formula
	Field IS NULL
	Field IS NOT NULL
2678 2679
         Field BETWEEN ...
         Field IN ...
unknown's avatar
unknown committed
2680 2681 2682
      */
      stat[0].key_dependent|=used_tables;

2683 2684
      bool is_const=1;
      for (uint i=0; i<num_values; i++)
2685
        is_const&= value[i]->const_item();
2686
      if (is_const)
2687
        stat[0].const_keys.merge(possible_keys);
2688 2689
      /*
	We can't always use indexes when comparing a string index to a
unknown's avatar
unknown committed
2690 2691
	number. cmp_type() is checked to allow compare of dates to numbers.
        eq_func is NEVER true when num_values > 1
2692
       */
2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706
      if (!eq_func)
        return;
      if (field->result_type() == STRING_RESULT)
      {
        if ((*value)->result_type() != STRING_RESULT)
        {
          if (field->cmp_type() != (*value)->result_type())
            return;
        }
        else
        {
          /*
            We can't use indexes if the effective collation
            of the operation differ from the field collation.
unknown's avatar
af  
unknown committed
2707

2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718
            We also cannot use index on a text column, as the column may
            contain 'x' 'x\t' 'x ' and 'read_next_same' will stop after
            'x' when searching for WHERE col='x '
          */
          if (field->cmp_type() == STRING_RESULT &&
              (((Field_str*)field)->charset() != cond->compare_collation() ||
               ((*value)->type() != Item::NULL_ITEM &&
                (field->flags & BLOB_FLAG) && !field->binary())))
            return;
        }
      }
unknown's avatar
unknown committed
2719 2720
    }
  }
2721
  DBUG_ASSERT(num_values == 1);
unknown's avatar
unknown committed
2722 2723 2724 2725 2726
  /*
    For the moment eq_func is always true. This slot is reserved for future
    extensions where we want to remembers other things than just eq comparisons
  */
  DBUG_ASSERT(eq_func);
unknown's avatar
unknown committed
2727
  /* Store possible eq field */
2728 2729
  (*key_fields)->field=		field;
  (*key_fields)->eq_func=	eq_func;
unknown's avatar
unknown committed
2730
  (*key_fields)->val=		*value;
2731 2732
  (*key_fields)->level=		and_level;
  (*key_fields)->optimize=	exists_optimize;
2733 2734 2735 2736 2737 2738 2739 2740
  /*
    If the condition has form "tbl.keypart = othertbl.field" and 
    othertbl.field can be NULL, there will be no matches if othertbl.field 
    has NULL value.
  */
  (*key_fields)->null_rejecting= (cond->functype() == Item_func::EQ_FUNC) &&
                                 ((*value)->type() == Item::FIELD_ITEM) &&
                                 ((Item_field*)*value)->field->maybe_null();
unknown's avatar
unknown committed
2741 2742 2743
  (*key_fields)++;
}

unknown's avatar
unknown committed
2744 2745 2746 2747
/*
  Add possible keys to array of possible keys originated from a simple predicate

  SYNPOSIS
2748
    add_key_equal_fields()
unknown's avatar
unknown committed
2749 2750
    key_fields			Pointer to add key, if usable
    and_level			And level, to be stored in KEY_FIELD
2751
    cond                        Condition predicate
unknown's avatar
unknown committed
2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765
    field			Field used in comparision
    eq_func			True if we used =, <=> or IS NULL
    value			Value used for comparison with field
				Is NULL for BETWEEN and IN    
    usable_tables		Tables which can be used for key optimization

  NOTES
    If field items f1 and f2 belong to the same multiple equality and
    a key is added for f1, the the same key is added for f2.

  RETURN
    *key_fields is incremented if we stored a key in the array
*/

2766 2767
static void
add_key_equal_fields(KEY_FIELD **key_fields, uint and_level,
unknown's avatar
unknown committed
2768
                     Item_func *cond, Item_field *field_item,
2769 2770 2771 2772
                     bool eq_func, Item **val,
                     uint num_values, table_map usable_tables)
{
  Field *field= field_item->field;
2773
  add_key_field(key_fields, and_level, cond, field,
2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787
                eq_func, val, num_values, usable_tables);
  Item_equal *item_equal= field_item->item_equal;
  if (item_equal)
  { 
    /*
      Add to the set of possible key values every substitution of
      the field for an equal field included into item_equal
    */
    Item_equal_iterator it(*item_equal);
    Item_field *item;
    while ((item= it++))
    {
      if (!field->eq(item->field))
      {
2788
        add_key_field(key_fields, and_level, cond, item->field,
2789 2790 2791 2792 2793 2794
                      eq_func, val, num_values, usable_tables);
      }
    }
  }
}

unknown's avatar
unknown committed
2795
static void
2796
add_key_fields(KEY_FIELD **key_fields,uint *and_level,
unknown's avatar
unknown committed
2797 2798 2799 2800
	       COND *cond, table_map usable_tables)
{
  if (cond->type() == Item_func::COND_ITEM)
  {
unknown's avatar
unknown committed
2801
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
2802 2803 2804 2805 2806 2807
    KEY_FIELD *org_key_fields= *key_fields;

    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
    {
      Item *item;
      while ((item=li++))
2808
	add_key_fields(key_fields,and_level,item,usable_tables);
unknown's avatar
unknown committed
2809
      for (; org_key_fields != *key_fields ; org_key_fields++)
2810
	org_key_fields->level= *and_level;
unknown's avatar
unknown committed
2811 2812 2813 2814
    }
    else
    {
      (*and_level)++;
2815
      add_key_fields(key_fields,and_level,li++,usable_tables);
unknown's avatar
unknown committed
2816 2817 2818 2819 2820
      Item *item;
      while ((item=li++))
      {
	KEY_FIELD *start_key_fields= *key_fields;
	(*and_level)++;
2821
	add_key_fields(key_fields,and_level,item,usable_tables);
unknown's avatar
unknown committed
2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836
	*key_fields=merge_key_fields(org_key_fields,start_key_fields,
				     *key_fields,++(*and_level));
      }
    }
    return;
  }
  /* If item is of type 'field op field/constant' add it to key_fields */

  if (cond->type() != Item::FUNC_ITEM)
    return;
  Item_func *cond_func= (Item_func*) cond;
  switch (cond_func->select_optimize()) {
  case Item_func::OPTIMIZE_NONE:
    break;
  case Item_func::OPTIMIZE_KEY:
unknown's avatar
unknown committed
2837 2838
  {
    // BETWEEN, IN, NE
2839
    if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
unknown's avatar
unknown committed
2840
	!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854
    {
      Item **values= cond_func->arguments()+1;
      if (cond_func->functype() == Item_func::NE_FUNC &&
        cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
	     !(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
        values--;
      add_key_equal_fields(key_fields, *and_level, cond_func,
                           (Item_field*) (cond_func->key_item()->real_item()),
                           cond_func->argument_count() == 2 &&
                           cond_func->functype() == Item_func::IN_FUNC,
                           values,
                           cond_func->argument_count()-1,
                           usable_tables);
    }
unknown's avatar
unknown committed
2855
    break;
unknown's avatar
unknown committed
2856
  }
unknown's avatar
unknown committed
2857 2858 2859 2860 2861
  case Item_func::OPTIMIZE_OP:
  {
    bool equal_func=(cond_func->functype() == Item_func::EQ_FUNC ||
		     cond_func->functype() == Item_func::EQUAL_FUNC);

2862
    if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
unknown's avatar
unknown committed
2863
	!(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
2864
    {
2865
      add_key_equal_fields(key_fields, *and_level, cond_func,
2866 2867 2868
	                (Item_field*) (cond_func->arguments()[0])->real_item(),
		           equal_func,
		           cond_func->arguments()+1, 1, usable_tables);
unknown's avatar
unknown committed
2869
    }
unknown's avatar
unknown committed
2870
    if (cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
2871
	cond_func->functype() != Item_func::LIKE_FUNC &&
unknown's avatar
unknown committed
2872
	!(cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
2873
    {
2874
      add_key_equal_fields(key_fields, *and_level, cond_func, 
2875 2876 2877
                       (Item_field*) (cond_func->arguments()[1])->real_item(),
		           equal_func,
		           cond_func->arguments(),1,usable_tables);
unknown's avatar
unknown committed
2878 2879 2880 2881 2882
    }
    break;
  }
  case Item_func::OPTIMIZE_NULL:
    /* column_name IS [NOT] NULL */
2883
    if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
unknown's avatar
unknown committed
2884
	!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
2885
    {
2886
      Item *tmp=new Item_null;
2887
      if (unlikely(!tmp))                       // Should never be true
unknown's avatar
unknown committed
2888
	return;
2889
      add_key_equal_fields(key_fields, *and_level, cond_func,
2890
		    (Item_field*) (cond_func->arguments()[0])->real_item(),
unknown's avatar
unknown committed
2891
		    cond_func->functype() == Item_func::ISNULL_FUNC,
2892
		    &tmp, 1, usable_tables);
unknown's avatar
unknown committed
2893 2894
    }
    break;
2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908
  case Item_func::OPTIMIZE_EQUAL:
    Item_equal *item_equal= (Item_equal *) cond;
    Item *const_item= item_equal->get_const();
    Item_equal_iterator it(*item_equal);
    Item_field *item;
    if (const_item)
    {
      /*
        For each field field1 from item_equal consider the equality 
        field1=const_item as a condition allowing an index access of the table
        with field1 by the keys value of field1.
      */   
      while ((item= it++))
      {
unknown's avatar
unknown committed
2909
        add_key_field(key_fields, *and_level, cond_func, item->field,
2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928
                      TRUE, &const_item, 1, usable_tables);
      }
    }
    else 
    {
      /*
        Consider all pairs of different fields included into item_equal.
        For each of them (field1, field1) consider the equality 
        field1=field2 as a condition allowing an index access of the table
        with field1 by the keys value of field2.
      */   
      Item_equal_iterator fi(*item_equal);
      while ((item= fi++))
      {
        Field *field= item->field;
        while ((item= it++))
        {
          if (!field->eq(item->field))
          {
unknown's avatar
unknown committed
2929
            add_key_field(key_fields, *and_level, cond_func, field,
2930 2931 2932 2933 2934 2935 2936
                          TRUE, (Item **) &item, 1, usable_tables);
          }
        }
        it.rewind();
      }
    }
    break;
unknown's avatar
unknown committed
2937 2938 2939 2940
  }
}

/*
2941 2942
  Add all keys with uses 'field' for some keypart
  If field->and_level != and_level then only mark key_part as const_part
unknown's avatar
unknown committed
2943 2944 2945
*/

static uint
2946
max_part_bit(key_part_map bits)
unknown's avatar
unknown committed
2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959
{
  uint found;
  for (found=0; bits & 1 ; found++,bits>>=1) ;
  return found;
}

static void
add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
{
  Field *field=key_field->field;
  TABLE *form= field->table;
  KEYUSE keyuse;

2960
  if (key_field->eq_func && !(key_field->optimize & KEY_OPTIMIZE_EXISTS))
unknown's avatar
unknown committed
2961
  {
2962
    for (uint key=0 ; key < form->s->keys ; key++)
unknown's avatar
unknown committed
2963
    {
2964
      if (!(form->keys_in_use_for_query.is_set(key)))
unknown's avatar
unknown committed
2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977
	continue;
      if (form->key_info[key].flags & HA_FULLTEXT)
	continue;    // ToDo: ft-keys in non-ft queries.   SerG

      uint key_parts= (uint) form->key_info[key].key_parts;
      for (uint part=0 ; part <  key_parts ; part++)
      {
	if (field->eq(form->key_info[key].key_part[part].field))
	{
	  keyuse.table= field->table;
	  keyuse.val =  key_field->val;
	  keyuse.key =  key;
	  keyuse.keypart=part;
2978
	  keyuse.keypart_map= (key_part_map) 1 << part;
unknown's avatar
unknown committed
2979
	  keyuse.used_tables=key_field->val->used_tables();
2980
	  keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL;
2981
          keyuse.null_rejecting= key_field->null_rejecting;
unknown's avatar
unknown committed
2982 2983 2984 2985 2986 2987 2988
	  VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
	}
      }
    }
  }
}

unknown's avatar
unknown committed
2989 2990 2991

#define FT_KEYPART   (MAX_REF_PARTS+10)

unknown's avatar
unknown committed
2992 2993 2994 2995
static void
add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
            JOIN_TAB *stat,COND *cond,table_map usable_tables)
{
2996
  Item_func_match *cond_func=NULL;
unknown's avatar
unknown committed
2997

2998 2999 3000
  if (!cond)
    return;

3001 3002
  if (cond->type() == Item::FUNC_ITEM)
  {
3003 3004 3005
    Item_func *func=(Item_func *)cond;
    Item_func::Functype functype=  func->functype();
    if (functype == Item_func::FT_FUNC)
3006
      cond_func=(Item_func_match *)cond;
3007 3008 3009 3010
    else if (func->arg_count == 2)
    {
      Item_func *arg0=(Item_func *)(func->arguments()[0]),
                *arg1=(Item_func *)(func->arguments()[1]);
3011
      if (arg1->const_item()  &&
3012 3013
          ((functype == Item_func::GE_FUNC && arg1->val_real() > 0) ||
           (functype == Item_func::GT_FUNC && arg1->val_real() >=0))  &&
3014 3015
           arg0->type() == Item::FUNC_ITEM            &&
           arg0->functype() == Item_func::FT_FUNC)
3016
        cond_func=(Item_func_match *) arg0;
3017
      else if (arg0->const_item() &&
3018 3019
               ((functype == Item_func::LE_FUNC && arg0->val_real() > 0) ||
                (functype == Item_func::LT_FUNC && arg0->val_real() >=0)) &&
3020
                arg1->type() == Item::FUNC_ITEM          &&
3021
                arg1->functype() == Item_func::FT_FUNC)
3022 3023
        cond_func=(Item_func_match *) arg1;
    }
3024 3025 3026
  }
  else if (cond->type() == Item::COND_ITEM)
  {
unknown's avatar
unknown committed
3027
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
3028 3029 3030 3031 3032

    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
    {
      Item *item;
      while ((item=li++))
3033
        add_ft_keys(keyuse_array,stat,item,usable_tables);
3034 3035 3036
    }
  }

3037 3038
  if (!cond_func || cond_func->key == NO_SUCH_KEY ||
      !(usable_tables & cond_func->table->map))
3039
    return;
unknown's avatar
unknown committed
3040 3041 3042

  KEYUSE keyuse;
  keyuse.table= cond_func->table;
3043
  keyuse.val =  cond_func;
unknown's avatar
unknown committed
3044
  keyuse.key =  cond_func->key;
unknown's avatar
unknown committed
3045
  keyuse.keypart= FT_KEYPART;
3046
  keyuse.used_tables=cond_func->key_item()->used_tables();
unknown's avatar
unknown committed
3047
  keyuse.optimize= 0;
unknown's avatar
unknown committed
3048
  keyuse.keypart_map= 0;
unknown's avatar
unknown committed
3049 3050 3051
  VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
}

3052

unknown's avatar
unknown committed
3053 3054 3055
static int
sort_keyuse(KEYUSE *a,KEYUSE *b)
{
3056
  int res;
unknown's avatar
unknown committed
3057 3058 3059 3060 3061 3062
  if (a->table->tablenr != b->table->tablenr)
    return (int) (a->table->tablenr - b->table->tablenr);
  if (a->key != b->key)
    return (int) (a->key - b->key);
  if (a->keypart != b->keypart)
    return (int) (a->keypart - b->keypart);
3063
  // Place const values before other ones
3064 3065
  if ((res= test((a->used_tables & ~OUTER_REF_TABLE_BIT)) -
       test((b->used_tables & ~OUTER_REF_TABLE_BIT))))
3066 3067 3068 3069
    return res;
  /* Place rows that are not 'OPTIMIZE_REF_OR_NULL' first */
  return (int) ((a->optimize & KEY_OPTIMIZE_REF_OR_NULL) -
		(b->optimize & KEY_OPTIMIZE_REF_OR_NULL));
unknown's avatar
unknown committed
3070 3071 3072 3073
}


/*
3074
  Update keyuse array with all possible keys we can use to fetch rows
3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090
  
  SYNOPSIS
    update_ref_and_keys()
      thd 
      keyuse     OUT Put here ordered array of KEYUSE structures
      join_tab       Array in tablenr_order
      tables         Number of tables in join
      cond           WHERE condition (note that the function analyzes 
                     join_tab[i]->on_expr too)
      normal_tables  tables not inner w.r.t some outer join (ones for which
                     we can make ref access based the WHERE clause)
      select_lex     current SELECT
      
  RETURN 
   0 - OK
   1 - Out of memory.
unknown's avatar
unknown committed
3091 3092 3093
*/

static bool
3094
update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
unknown's avatar
unknown committed
3095 3096
		    uint tables, COND *cond, COND_EQUAL *cond_equal,
                    table_map normal_tables, SELECT_LEX *select_lex)
unknown's avatar
unknown committed
3097 3098
{
  uint	and_level,i,found_eq_constant;
unknown's avatar
unknown committed
3099
  KEY_FIELD *key_fields, *end, *field;
unknown's avatar
unknown committed
3100 3101 3102 3103
  uint m= 1;
  
  if (cond_equal && cond_equal->max_members)
    m= cond_equal->max_members;
unknown's avatar
unknown committed
3104

3105
  if (!(key_fields=(KEY_FIELD*)
unknown's avatar
merge  
unknown committed
3106
	thd->alloc(sizeof(key_fields[0])*
unknown's avatar
unknown committed
3107
		   (thd->lex->current_select->cond_count+1)*2*m)))
3108
    return TRUE; /* purecov: inspected */
unknown's avatar
unknown committed
3109 3110 3111 3112
  and_level= 0;
  field= end= key_fields;
  if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
    return TRUE;
3113
  if (cond)
unknown's avatar
unknown committed
3114
  {
3115
    add_key_fields(&end,&and_level,cond,normal_tables);
unknown's avatar
unknown committed
3116
    for (; field != end ; field++)
unknown's avatar
unknown committed
3117
    {
unknown's avatar
unknown committed
3118 3119 3120 3121 3122
      add_key_part(keyuse,field);
      /* Mark that we can optimize LEFT JOIN */
      if (field->val->type() == Item::NULL_ITEM &&
	  !field->field->real_maybe_null())
	field->field->table->reginfo.not_exists_optimize=1;
unknown's avatar
unknown committed
3123
    }
unknown's avatar
unknown committed
3124
  }
3125
  for (i=0 ; i < tables ; i++)
unknown's avatar
unknown committed
3126
  {
3127 3128 3129 3130 3131 3132 3133 3134 3135
    /*
      Block the creation of keys for inner tables of outer joins.
      Here only the outer joins that can not be converted to
      inner joins are left and all nests that can be eliminated
      are flattened.
      In the future when we introduce conditional accesses
      for inner tables in outer joins these keys will be taken
      into account as well.
    */ 
unknown's avatar
unknown committed
3136
    if (*join_tab[i].on_expr_ref)
unknown's avatar
unknown committed
3137
    {
3138
      add_key_fields(&end,&and_level,*join_tab[i].on_expr_ref,
3139
		     join_tab[i].table->map);
unknown's avatar
unknown committed
3140
    }
3141 3142 3143 3144 3145 3146 3147 3148
    else 
    {
      TABLE_LIST *tab= join_tab[i].table->pos_in_table_list;
      TABLE_LIST *embedding= tab->embedding;
      if (embedding)
      {
        NESTED_JOIN *nested_join= embedding->nested_join;
        if (nested_join->join_list.head() == tab)
unknown's avatar
unknown committed
3149
          add_key_fields(&end, &and_level, embedding->on_expr,
3150 3151 3152
                         nested_join->used_tables);
      }
    }
unknown's avatar
unknown committed
3153
  }
3154
  /* fill keyuse with found key parts */
unknown's avatar
unknown committed
3155
  for ( ; field != end ; field++)
3156
    add_key_part(keyuse,field);
unknown's avatar
unknown committed
3157

3158
  if (select_lex->ftfunc_list->elements)
unknown's avatar
unknown committed
3159 3160 3161 3162 3163
  {
    add_ft_keys(keyuse,join_tab,cond,normal_tables);
  }

  /*
3164
    Sort the array of possible keys and remove the following key parts:
3165
    - ref if there is a keypart which is a ref and a const.
3166 3167 3168 3169 3170 3171
      (e.g. if there is a key(a,b) and the clause is a=3 and b=7 and b=t2.d,
      then we skip the key part corresponding to b=t2.d)
    - keyparts without previous keyparts
      (e.g. if there is a key(a,b,c) but only b < 5 (or a=2 and c < 3) is
      used in the query, we drop the partial key parts from consideration).
    Special treatment for ft-keys.
unknown's avatar
unknown committed
3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188
  */
  if (keyuse->elements)
  {
    KEYUSE end,*prev,*save_pos,*use;

    qsort(keyuse->buffer,keyuse->elements,sizeof(KEYUSE),
	  (qsort_cmp) sort_keyuse);

    bzero((char*) &end,sizeof(end));		/* Add for easy testing */
    VOID(insert_dynamic(keyuse,(gptr) &end));

    use=save_pos=dynamic_element(keyuse,0,KEYUSE*);
    prev=&end;
    found_eq_constant=0;
    for (i=0 ; i < keyuse->elements-1 ; i++,use++)
    {
      if (!use->used_tables)
3189
	use->table->const_key_parts[use->key]|= use->keypart_map;
unknown's avatar
unknown committed
3190 3191
      if (use->keypart != FT_KEYPART)
      {
3192 3193 3194 3195 3196 3197 3198 3199
	if (use->key == prev->key && use->table == prev->table)
	{
	  if (prev->keypart+1 < use->keypart ||
	      prev->keypart == use->keypart && found_eq_constant)
	    continue;				/* remove */
	}
	else if (use->keypart != 0)		// First found must be 0
	  continue;
unknown's avatar
unknown committed
3200 3201 3202 3203 3204 3205 3206 3207
      }

      *save_pos= *use;
      prev=use;
      found_eq_constant= !use->used_tables;
      /* Save ptr to first use */
      if (!use->table->reginfo.join_tab->keyuse)
	use->table->reginfo.join_tab->keyuse=save_pos;
3208
      use->table->reginfo.join_tab->checked_keys.set_bit(use->key);
unknown's avatar
unknown committed
3209 3210 3211 3212 3213 3214 3215 3216 3217
      save_pos++;
    }
    i=(uint) (save_pos-(KEYUSE*) keyuse->buffer);
    VOID(set_dynamic(keyuse,(gptr) &end,i));
    keyuse->elements=i;
  }
  return FALSE;
}

3218
/*
unknown's avatar
af  
unknown committed
3219
  Update some values in keyuse for faster choose_plan() loop
3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236
*/

static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array)
{
  KEYUSE *end,*keyuse= dynamic_element(keyuse_array, 0, KEYUSE*);

  for (end= keyuse+ keyuse_array->elements ; keyuse < end ; keyuse++)
  {
    table_map map;
    /*
      If we find a ref, assume this table matches a proportional
      part of this table.
      For example 100 records matching a table with 5000 records
      gives 5000/100 = 50 records per key
      Constant tables are ignored.
      To avoid bad matches, we don't make ref_table_rows less than 100.
    */
unknown's avatar
unknown committed
3237
    keyuse->ref_table_rows= ~(ha_rows) 0;	// If no ref
3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249
    if (keyuse->used_tables &
	(map= (keyuse->used_tables & ~join->const_table_map &
	       ~OUTER_REF_TABLE_BIT)))
    {
      uint tablenr;
      for (tablenr=0 ; ! (map & 1) ; map>>=1, tablenr++) ;
      if (map == 1)			// Only one table
      {
	TABLE *tmp_table=join->all_tables[tablenr];
	keyuse->ref_table_rows= max(tmp_table->file->records, 100);
      }
    }
unknown's avatar
af  
unknown committed
3250 3251 3252 3253 3254 3255 3256 3257 3258 3259
    /*
      Outer reference (external field) is constant for single executing
      of subquery
    */
    if (keyuse->used_tables == OUTER_REF_TABLE_BIT)
      keyuse->ref_table_rows= 1;
  }
}


3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321
/*
  Discover the indexes that can be used for GROUP BY or DISTINCT queries.

  SYNOPSIS
    add_group_and_distinct_keys()
    join
    join_tab

  DESCRIPTION
    If the query has a GROUP BY clause, find all indexes that contain all
    GROUP BY fields, and add those indexes to join->const_keys.
    If the query has a DISTINCT clause, find all indexes that contain all
    SELECT fields, and add those indexes to join->const_keys.
    This allows later on such queries to be processed by a
    QUICK_GROUP_MIN_MAX_SELECT.

  RETURN
    None
*/

static void
add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab)
{
  List<Item_field> indexed_fields;
  List_iterator<Item_field> indexed_fields_it(indexed_fields);
  ORDER      *cur_group;
  Item_field *cur_item;
  key_map possible_keys(0);

  if (join->group_list)
  { /* Collect all query fields referenced in the GROUP clause. */
    for (cur_group= join->group_list; cur_group; cur_group= cur_group->next)
      (*cur_group->item)->walk(&Item::collect_item_field_processor,
                               (byte*) &indexed_fields);
  }
  else if (join->select_distinct)
  { /* Collect all query fields referenced in the SELECT clause. */
    List<Item> &select_items= join->fields_list;
    List_iterator<Item> select_items_it(select_items);
    Item *item;
    while ((item= select_items_it++))
      item->walk(&Item::collect_item_field_processor, (byte*) &indexed_fields);
  }
  else
    return;

  if (indexed_fields.elements == 0)
    return;

  /* Intersect the keys of all group fields. */
  cur_item= indexed_fields_it++;
  possible_keys.merge(cur_item->field->part_of_key);
  while ((cur_item= indexed_fields_it++))
  {
    possible_keys.intersect(cur_item->field->part_of_key);
  }

  if (!possible_keys.is_clear_all())
    join_tab->const_keys.merge(possible_keys);
}


unknown's avatar
af  
unknown committed
3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492
/*****************************************************************************
  Go through all combinations of not marked tables and find the one
  which uses least records
*****************************************************************************/

/* Save const tables first as used tables */

static void
set_position(JOIN *join,uint idx,JOIN_TAB *table,KEYUSE *key)
{
  join->positions[idx].table= table;
  join->positions[idx].key=key;
  join->positions[idx].records_read=1.0;	/* This is a const table */

  /* Move the const table as down as possible in best_ref */
  JOIN_TAB **pos=join->best_ref+idx+1;
  JOIN_TAB *next=join->best_ref[idx];
  for (;next != table ; pos++)
  {
    JOIN_TAB *tmp=pos[0];
    pos[0]=next;
    next=tmp;
  }
  join->best_ref[idx]=table;
}


/*
  Find the best access path for an extension of a partial execution plan and
  add this path to the plan.

  SYNOPSIS
    best_access_path()
    join             pointer to the structure providing all context info
                     for the query
    s                the table to be joined by the function
    thd              thread for the connection that submitted the query
    remaining_tables set of tables not included into the partial plan yet
    idx              the length of the partial plan
    record_count     estimate for the number of records returned by the partial
                     plan
    read_time        the cost of the partial plan

  DESCRIPTION
    The function finds the best access path to table 's' from the passed
    partial plan where an access path is the general term for any means to
    access the data in 's'. An access path may use either an index or a scan,
    whichever is cheaper. The input partial plan is passed via the array
    'join->positions' of length 'idx'. The chosen access method for 's' and its
    cost are stored in 'join->positions[idx]'.

  RETURN
    None
*/

static void
best_access_path(JOIN      *join,
                 JOIN_TAB  *s,
                 THD       *thd,
                 table_map remaining_tables,
                 uint      idx,
                 double    record_count,
                 double    read_time)
{
  KEYUSE *best_key=         0;
  uint best_max_key_part=   0;
  my_bool found_constraint= 0;
  double best=              DBL_MAX;
  double best_time=         DBL_MAX;
  double records=           DBL_MAX;
  double tmp;
  ha_rows rec;

  DBUG_ENTER("best_access_path");

  if (s->keyuse)
  {                                            /* Use key if possible */
    TABLE *table= s->table;
    KEYUSE *keyuse,*start_key=0;
    double best_records= DBL_MAX;
    uint max_key_part=0;

    /* Test how we can use keys */
    rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE;  // Assumed records/key
    for (keyuse=s->keyuse ; keyuse->table == table ;)
    {
      key_part_map found_part= 0;
      table_map found_ref=     0;
      uint found_ref_or_null=  0;
      uint key=     keyuse->key;
      KEY *keyinfo= table->key_info+key;
      bool ft_key=  (keyuse->keypart == FT_KEYPART);

      /* Calculate how many key segments of the current key we can use */
      start_key= keyuse;
      do
      { /* for each keypart */
        uint keypart= keyuse->keypart;
        uint found_part_ref_or_null= KEY_OPTIMIZE_REF_OR_NULL;
        do
        {
          if (!(remaining_tables & keyuse->used_tables) &&
              !(found_ref_or_null & keyuse->optimize))
          {
            found_part|= keyuse->keypart_map;
            found_ref|=  keyuse->used_tables;
            if (rec > keyuse->ref_table_rows)
              rec= keyuse->ref_table_rows;
            found_part_ref_or_null&= keyuse->optimize;
          }
          keyuse++;
          found_ref_or_null|= found_part_ref_or_null;
        } while (keyuse->table == table && keyuse->key == key &&
                 keyuse->keypart == keypart);
      } while (keyuse->table == table && keyuse->key == key);

      /*
        Assume that that each key matches a proportional part of table.
      */
      if (!found_part && !ft_key)
        continue;                               // Nothing usable found

      if (rec < MATCHING_ROWS_IN_OTHER_TABLE)
        rec= MATCHING_ROWS_IN_OTHER_TABLE;      // Fix for small tables

      /*
        ft-keys require special treatment
      */
      if (ft_key)
      {
        /*
          Really, there should be records=0.0 (yes!)
          but 1.0 would be probably safer
        */
        tmp= prev_record_reads(join, found_ref);
        records= 1.0;
      }
      else
      {
        found_constraint= 1;
        /*
          Check if we found full key
        */
        if (found_part == PREV_BITS(uint,keyinfo->key_parts) &&
            !found_ref_or_null)
        {                                         /* use eq key */
          max_key_part= (uint) ~0;
          if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
          {
            tmp = prev_record_reads(join, found_ref);
            records=1.0;
          }
          else
          {
            if (!found_ref)
            {                                     /* We found a const key */
              if (table->quick_keys.is_set(key))
                records= (double) table->quick_rows[key];
              else
              {
                /* quick_range couldn't use key! */
                records= (double) s->records/rec;
              }
            }
            else
            {
              if (!(records=keyinfo->rec_per_key[keyinfo->key_parts-1]))
              {                                   /* Prefer longer keys */
                records=
                  ((double) s->records / (double) rec *
                   (1.0 +
3493 3494
                    ((double) (table->s->max_key_length-keyinfo->key_length) /
                     (double) table->s->max_key_length)));
unknown's avatar
af  
unknown committed
3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520
                if (records < 2.0)
                  records=2.0;               /* Can't be as good as a unique */
              }
            }
            /* Limit the number of matched rows */
            tmp = records;
            set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
            if (table->used_keys.is_set(key))
            {
              /* we can use only index tree */
              uint keys_per_block= table->file->block_size/2/
                (keyinfo->key_length+table->file->ref_length)+1;
              tmp = record_count*(tmp+keys_per_block-1)/keys_per_block;
            }
            else
              tmp = record_count*min(tmp,s->worst_seeks);
          }
        }
        else
        {
          /*
            Use as much key-parts as possible and a uniq key is better
            than a not unique key
            Set tmp to (previous record count) * (records / combination)
          */
          if ((found_part & 1) &&
unknown's avatar
unknown committed
3521
              (!(table->file->index_flags(key, 0, 0) & HA_ONLY_WHOLE_INDEX) ||
unknown's avatar
af  
unknown committed
3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540
               found_part == PREV_BITS(uint,keyinfo->key_parts)))
          {
            max_key_part=max_part_bit(found_part);
            /*
              Check if quick_range could determinate how many rows we
              will match
            */
            if (table->quick_keys.is_set(key) &&
                table->quick_key_parts[key] == max_key_part)
              tmp= records= (double) table->quick_rows[key];
            else
            {
              /* Check if we have statistic about the distribution */
              if ((records = keyinfo->rec_per_key[max_key_part-1]))
                tmp = records;
              else
              {
                /*
                  Assume that the first key part matches 1% of the file
unknown's avatar
unknown committed
3541
                  and that the whole key matches 10 (duplicates) or 1
unknown's avatar
af  
unknown committed
3542 3543 3544 3545 3546 3547 3548
                  (unique) records.
                  Assume also that more key matches proportionally more
                  records
                  This gives the formula:
                  records = (x * (b-a) + a*c-b)/(c-1)

                  b = records matched by whole key
unknown's avatar
unknown committed
3549
                  a = records matched by first key part (1% of all records?)
unknown's avatar
af  
unknown committed
3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564
                  c = number of key parts in key
                  x = used key parts (1 <= x <= c)
                */
                double rec_per_key;
                if (!(rec_per_key=(double)
                      keyinfo->rec_per_key[keyinfo->key_parts-1]))
                  rec_per_key=(double) s->records/rec+1;

                if (!s->records)
                  tmp = 0;
                else if (rec_per_key/(double) s->records >= 0.01)
                  tmp = rec_per_key;
                else
                {
                  double a=s->records*0.01;
unknown's avatar
unknown committed
3565 3566 3567 3568 3569 3570
                  if (keyinfo->key_parts > 1)
                    tmp= (max_key_part * (rec_per_key - a) +
                          a*keyinfo->key_parts - rec_per_key)/
                         (keyinfo->key_parts-1);
                  else
                    tmp= a;
unknown's avatar
af  
unknown committed
3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663
                  set_if_bigger(tmp,1.0);
                }
                records = (ulong) tmp;
              }
              /*
                If quick_select was used on a part of this key, we know
                the maximum number of rows that the key can match.
              */
              if (table->quick_keys.is_set(key) &&
                  table->quick_key_parts[key] <= max_key_part &&
                  records > (double) table->quick_rows[key])
                tmp= records= (double) table->quick_rows[key];
              else if (found_ref_or_null)
              {
                /* We need to do two key searches to find key */
                tmp *= 2.0;
                records *= 2.0;
              }
            }
            /* Limit the number of matched rows */
            set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
            if (table->used_keys.is_set(key))
            {
              /* we can use only index tree */
              uint keys_per_block= table->file->block_size/2/
                (keyinfo->key_length+table->file->ref_length)+1;
              tmp = record_count*(tmp+keys_per_block-1)/keys_per_block;
            }
            else
              tmp = record_count*min(tmp,s->worst_seeks);
          }
          else
            tmp = best_time;                    // Do nothing
        }
      } /* not ft_key */
      if (tmp < best_time - records/(double) TIME_FOR_COMPARE)
      {
        best_time= tmp + records/(double) TIME_FOR_COMPARE;
        best= tmp;
        best_records= records;
        best_key= start_key;
        best_max_key_part= max_key_part;
      }
    }
    records= best_records;
  }

  /*
    Don't test table scan if it can't be better.
    Prefer key lookup if we would use the same key for scanning.

    Don't do a table scan on InnoDB tables, if we can read the used
    parts of the row from any of the used index.
    This is because table scans uses index and we would not win
    anything by using a table scan.
  */
  if ((records >= s->found_records || best > s->read_time) &&
      !(s->quick && best_key && s->quick->index == best_key->key &&
        best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
      !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
        ! s->table->used_keys.is_clear_all() && best_key) &&
      !(s->table->force_index && best_key))
  {                                             // Check full join
    ha_rows rnd_records= s->found_records;
    /*
      If there is a restriction on the table, assume that 25% of the
      rows can be skipped on next part.
      This is to force tables that this table depends on before this
      table
    */
    if (found_constraint)
      rnd_records-= rnd_records/4;

    /*
      Range optimizer never proposes a RANGE if it isn't better
      than FULL: so if RANGE is present, it's always preferred to FULL.
      Here we estimate its cost.
    */
    if (s->quick)
    {
      /*
        For each record we:
        - read record range through 'quick'
        - skip rows which does not satisfy WHERE constraints
      */
      tmp= record_count *
        (s->quick->read_time +
         (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE);
    }
    else
    {
      /* Estimate cost of reading table. */
      tmp= s->table->file->scan_time();
unknown's avatar
unknown committed
3664
      if (s->table->map & join->outer_join)     // Can't use join cache
unknown's avatar
af  
unknown committed
3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751
      {
        /*
          For each record we have to:
          - read the whole table record 
          - skip rows which does not satisfy join condition
        */
        tmp= record_count *
          (tmp +
           (s->records - rnd_records)/(double) TIME_FOR_COMPARE);
      }
      else
      {
        /* We read the table as many times as join buffer becomes full. */
        tmp*= (1.0 + floor((double) cache_record_length(join,idx) *
                           record_count /
                           (double) thd->variables.join_buff_size));
        /* 
            We don't make full cartesian product between rows in the scanned
           table and existing records because we skip all rows from the
           scanned table, which does not satisfy join condition when 
           we read the table (see flush_cached_records for details). Here we
           take into account cost to read and skip these records.
        */
        tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
      }
    }

    /*
      We estimate the cost of evaluating WHERE clause for found records
      as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus
      tmp give us total cost of using TABLE SCAN
    */
    if (best == DBL_MAX ||
        (tmp  + record_count/(double) TIME_FOR_COMPARE*rnd_records <
         best + record_count/(double) TIME_FOR_COMPARE*records))
    {
      /*
        If the table has a range (s->quick is set) make_join_select()
        will ensure that this will be used
      */
      best= tmp;
      records= rows2double(rnd_records);
      best_key= 0;
    }
  }

  /* Update the cost information for the current partial plan */
  join->positions[idx].records_read= records;
  join->positions[idx].read_time=    best;
  join->positions[idx].key=          best_key;
  join->positions[idx].table=        s;

  if (!best_key &&
      idx == join->const_tables &&
      s->table == join->sort_by_table &&
      join->unit->select_limit_cnt >= records)
    join->sort_by_table= (TABLE*) 1;  // Must use temporary table

  DBUG_VOID_RETURN;
}


/*
  Selects and invokes a search strategy for an optimal query plan.

  SYNOPSIS
    choose_plan()
    join        pointer to the structure providing all context info for
                the query
    join_tables set of the tables in the query

  DESCRIPTION
    The function checks user-configurable parameters that control the search
    strategy for an optimal plan, selects the search method and then invokes
    it. Each specific optimization procedure stores the final optimal plan in
    the array 'join->best_positions', and the cost of the plan in
    'join->best_read'.

  RETURN
    None
*/

static void
choose_plan(JOIN *join, table_map join_tables)
{
  uint search_depth= join->thd->variables.optimizer_search_depth;
  uint prune_level=  join->thd->variables.optimizer_prune_level;
3752
  bool straight_join= join->select_options & SELECT_STRAIGHT_JOIN;
unknown's avatar
af  
unknown committed
3753 3754
  DBUG_ENTER("choose_plan");

3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766
  /*
    if (SELECT_STRAIGHT_JOIN option is set)
      reorder tables so dependent tables come after tables they depend 
      on, otherwise keep tables in the order they were specified in the query 
    else
      Apply heuristic: pre-sort all access plans with respect to the number of
      records accessed.
  */
  qsort(join->best_ref + join->const_tables, join->tables - join->const_tables,
        sizeof(JOIN_TAB*), straight_join?join_tab_cmp_straight:join_tab_cmp);
  
  if (straight_join)
unknown's avatar
af  
unknown committed
3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788
  {
    optimize_straight_join(join, join_tables);
  }
  else
  {
    if (search_depth == MAX_TABLES+2)
    { /*
        TODO: 'MAX_TABLES+2' denotes the old implementation of find_best before
        the greedy version. Will be removed when greedy_search is approved.
      */
      join->best_read= DBL_MAX;
      find_best(join, join_tables, join->const_tables, 1.0, 0.0);
    } 
    else
    {
      if (search_depth == 0)
        /* Automatically determine a reasonable value for 'search_depth' */
        search_depth= determine_search_depth(join);
      greedy_search(join, join_tables, search_depth, prune_level);
    }
  }

3789 3790 3791 3792 3793 3794
  /* 
    Store the cost of this query into a user variable
    Don't update last_query_cost for 'show status' command
  */
  if (join->thd->lex->orig_sql_command != SQLCOM_SHOW_STATUS)
    last_query_cost= join->best_read;
unknown's avatar
af  
unknown committed
3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818

  DBUG_VOID_RETURN;
}


/*
  Compare two JOIN_TAB objects based on the number of accessed records.

  SYNOPSIS
    join_tab_cmp()
    ptr1 pointer to first JOIN_TAB object
    ptr2 pointer to second JOIN_TAB object

  RETURN
    1  if first is bigger
    -1 if second is bigger
    0  if equal
*/

static int
join_tab_cmp(const void* ptr1, const void* ptr2)
{
  JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
  JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;
unknown's avatar
unknown committed
3819 3820 3821 3822 3823

  if (jt1->dependent & jt2->table->map)
    return 1;
  if (jt2->dependent & jt1->table->map)
    return -1;  
unknown's avatar
af  
unknown committed
3824 3825
  if (jt1->found_records > jt2->found_records)
    return 1;
unknown's avatar
unknown committed
3826 3827 3828
  if (jt1->found_records < jt2->found_records)
    return -1; 
  return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
unknown's avatar
af  
unknown committed
3829 3830 3831
}


3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848
/* 
  Same as join_tab_cmp, but for use with SELECT_STRAIGHT_JOIN.
*/

static int
join_tab_cmp_straight(const void* ptr1, const void* ptr2)
{
  JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
  JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;

  if (jt1->dependent & jt2->table->map)
    return 1;
  if (jt2->dependent & jt1->table->map)
    return -1;
  return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
}

unknown's avatar
af  
unknown committed
3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930
/*
  Heuristic procedure to automatically guess a reasonable degree of
  exhaustiveness for the greedy search procedure.

  SYNOPSIS
    determine_search_depth()
    join   pointer to the structure providing all context info for the query

  DESCRIPTION
    The procedure estimates the optimization time and selects a search depth
    big enough to result in a near-optimal QEP, that doesn't take too long to
    find. If the number of tables in the query exceeds some constant, then
    search_depth is set to this constant.

  NOTES
    This is an extremely simplistic implementation that serves as a stub for a
    more advanced analysis of the join. Ideally the search depth should be
    determined by learning from previous query optimizations, because it will
    depend on the CPU power (and other factors).

  RETURN
    A positive integer that specifies the search depth (and thus the
    exhaustiveness) of the depth-first search algorithm used by
    'greedy_search'.
*/

static uint
determine_search_depth(JOIN *join)
{
  uint table_count=  join->tables - join->const_tables;
  uint search_depth;
  /* TODO: this value should be determined dynamically, based on statistics: */
  uint max_tables_for_exhaustive_opt= 7;

  if (table_count <= max_tables_for_exhaustive_opt)
    search_depth= table_count+1; // use exhaustive for small number of tables
  else
    /*
      TODO: this value could be determined by some mapping of the form:
      depth : table_count -> [max_tables_for_exhaustive_opt..MAX_EXHAUSTIVE]
    */
    search_depth= max_tables_for_exhaustive_opt; // use greedy search

  return search_depth;
}


/*
  Select the best ways to access the tables in a query without reordering them.

  SYNOPSIS
    optimize_straight_join()
    join          pointer to the structure providing all context info for
                  the query
    join_tables   set of the tables in the query

  DESCRIPTION
    Find the best access paths for each query table and compute their costs
    according to their order in the array 'join->best_ref' (thus without
    reordering the join tables). The function calls sequentially
    'best_access_path' for each table in the query to select the best table
    access method. The final optimal plan is stored in the array
    'join->best_positions', and the corresponding cost in 'join->best_read'.

  NOTES
    This function can be applied to:
    - queries with STRAIGHT_JOIN
    - internally to compute the cost of an arbitrary QEP
    Thus 'optimize_straight_join' can be used at any stage of the query
    optimization process to finalize a QEP as it is.

  RETURN
    None
*/

static void
optimize_straight_join(JOIN *join, table_map join_tables)
{
  JOIN_TAB *s;
  uint idx= join->const_tables;
  double    record_count= 1.0;
  double    read_time=    0.0;
3931
 
unknown's avatar
af  
unknown committed
3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192
  for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
  {
    /* Find the best access method from 's' to the current partial plan */
    best_access_path(join, s, join->thd, join_tables, idx, record_count, read_time);
    /* compute the cost of the new plan extended with 's' */
    record_count*= join->positions[idx].records_read;
    read_time+=    join->positions[idx].read_time;
    join_tables&= ~(s->table->map);
    ++idx;
  }

  read_time+= record_count / (double) TIME_FOR_COMPARE;
  if (join->sort_by_table &&
      join->sort_by_table != join->positions[join->const_tables].table->table)
    read_time+= record_count;  // We have to make a temp table
  memcpy((gptr) join->best_positions, (gptr) join->positions,
         sizeof(POSITION)*idx);
  join->best_read= read_time;
}


/*
  Find a good, possibly optimal, query execution plan (QEP) by a greedy search.

  SYNOPSIS
    join             pointer to the structure providing all context info
                     for the query
    remaining_tables set of tables not included into the partial plan yet
    search_depth     controlls the exhaustiveness of the search
    prune_level      the pruning heuristics that should be applied during
                     search

  DESCRIPTION
    The search procedure uses a hybrid greedy/exhaustive search with controlled
    exhaustiveness. The search is performed in N = card(remaining_tables)
    steps. Each step evaluates how promising is each of the unoptimized tables,
    selects the most promising table, and extends the current partial QEP with
    that table.  Currenly the most 'promising' table is the one with least
    expensive extension.
    There are two extreme cases:
    1. When (card(remaining_tables) < search_depth), the estimate finds the best
       complete continuation of the partial QEP. This continuation can be
       used directly as a result of the search.
    2. When (search_depth == 1) the 'best_extension_by_limited_search'
       consideres the extension of the current QEP with each of the remaining
       unoptimized tables.
    All other cases are in-between these two extremes. Thus the parameter
    'search_depth' controlls the exhaustiveness of the search. The higher the
    value, the longer the optimizaton time and possibly the better the
    resulting plan. The lower the value, the fewer alternative plans are
    estimated, but the more likely to get a bad QEP.

    All intermediate and final results of the procedure are stored in 'join':
    join->positions      modified for every partial QEP that is explored
    join->best_positions modified for the current best complete QEP
    join->best_read      modified for the current best complete QEP
    join->best_ref       might be partially reordered
    The final optimal plan is stored in 'join->best_positions', and its
    corresponding cost in 'join->best_read'.

  NOTES
    The following pseudocode describes the algorithm of 'greedy_search':

    procedure greedy_search
    input: remaining_tables
    output: pplan;
    {
      pplan = <>;
      do {
        (t, a) = best_extension(pplan, remaining_tables);
        pplan = concat(pplan, (t, a));
        remaining_tables = remaining_tables - t;
      } while (remaining_tables != {})
      return pplan;
    }

    where 'best_extension' is a placeholder for a procedure that selects the
    most "promising" of all tables in 'remaining_tables'.
    Currently this estimate is performed by calling
    'best_extension_by_limited_search' to evaluate all extensions of the
    current QEP of size 'search_depth', thus the complexity of 'greedy_search'
    mainly depends on that of 'best_extension_by_limited_search'.

    If 'best_extension()' == 'best_extension_by_limited_search()', then the
    worst-case complexity of this algorithm is <=
    O(N*N^search_depth/search_depth). When serch_depth >= N, then the
    complexity of greedy_search is O(N!).

    In the future, 'greedy_search' might be extended to support other
    implementations of 'best_extension', e.g. some simpler quadratic procedure.

  RETURN
    None
*/

static void
greedy_search(JOIN      *join,
              table_map remaining_tables,
              uint      search_depth,
              uint      prune_level)
{
  double    record_count= 1.0;
  double    read_time=    0.0;
  uint      idx= join->const_tables; // index into 'join->best_ref'
  uint      best_idx;
  uint      rem_size;    // cardinality of remaining_tables
  POSITION  best_pos;
  JOIN_TAB  *best_table; // the next plan node to be added to the curr QEP

  DBUG_ENTER("greedy_search");

  /* number of tables that remain to be optimized */
  rem_size= my_count_bits(remaining_tables);

  do {
    /* Find the extension of the current QEP with the lowest cost */
    join->best_read= DBL_MAX;
    best_extension_by_limited_search(join, remaining_tables, idx, record_count,
                                     read_time, search_depth, prune_level);

    if (rem_size <= search_depth)
    {
      /*
        'join->best_positions' contains a complete optimal extension of the
        current partial QEP.
      */
      DBUG_EXECUTE("opt", print_plan(join, read_time, record_count,
                                     join->tables, "optimal"););
      DBUG_VOID_RETURN;
    }

    /* select the first table in the optimal extension as most promising */
    best_pos= join->best_positions[idx];
    best_table= best_pos.table;
    /*
      Each subsequent loop of 'best_extension_by_limited_search' uses
      'join->positions' for cost estimates, therefore we have to update its
      value.
    */
    join->positions[idx]= best_pos;

    /* find the position of 'best_table' in 'join->best_ref' */
    best_idx= idx;
    JOIN_TAB *pos= join->best_ref[best_idx];
    while (pos && best_table != pos)
      pos= join->best_ref[++best_idx];
    DBUG_ASSERT((pos != NULL)); // should always find 'best_table'
    /* move 'best_table' at the first free position in the array of joins */
    swap_variables(JOIN_TAB*, join->best_ref[idx], join->best_ref[best_idx]);

    /* compute the cost of the new plan extended with 'best_table' */
    record_count*= join->positions[idx].records_read;
    read_time+=    join->positions[idx].read_time;

    remaining_tables&= ~(best_table->table->map);
    --rem_size;
    ++idx;

    DBUG_EXECUTE("opt",
                 print_plan(join, read_time, record_count, idx, "extended"););
  } while (TRUE);
}


/*
  Find a good, possibly optimal, query execution plan (QEP) by a possibly
  exhaustive search.

  SYNOPSIS
    best_extension_by_limited_search()
    join             pointer to the structure providing all context info for
                     the query
    remaining_tables set of tables not included into the partial plan yet
    idx              length of the partial QEP in 'join->positions';
                     since a depth-first search is used, also corresponds to
                     the current depth of the search tree;
                     also an index in the array 'join->best_ref';
    record_count     estimate for the number of records returned by the best
                     partial plan
    read_time        the cost of the best partial plan
    search_depth     maximum depth of the recursion and thus size of the found
                     optimal plan (0 < search_depth <= join->tables+1).
    prune_level      pruning heuristics that should be applied during optimization
                     (values: 0 = EXHAUSTIVE, 1 = PRUNE_BY_TIME_OR_ROWS)

  DESCRIPTION
    The procedure searches for the optimal ordering of the query tables in set
    'remaining_tables' of size N, and the corresponding optimal access paths to each
    table. The choice of a table order and an access path for each table
    constitutes a query execution plan (QEP) that fully specifies how to
    execute the query.
   
    The maximal size of the found plan is controlled by the parameter
    'search_depth'. When search_depth == N, the resulting plan is complete and
    can be used directly as a QEP. If search_depth < N, the found plan consists
    of only some of the query tables. Such "partial" optimal plans are useful
    only as input to query optimization procedures, and cannot be used directly
    to execute a query.

    The algorithm begins with an empty partial plan stored in 'join->positions'
    and a set of N tables - 'remaining_tables'. Each step of the algorithm
    evaluates the cost of the partial plan extended by all access plans for
    each of the relations in 'remaining_tables', expands the current partial
    plan with the access plan that results in lowest cost of the expanded
    partial plan, and removes the corresponding relation from
    'remaining_tables'. The algorithm continues until it either constructs a
    complete optimal plan, or constructs an optimal plartial plan with size =
    search_depth.

    The final optimal plan is stored in 'join->best_positions'. The
    corresponding cost of the optimal plan is in 'join->best_read'.

  NOTES
    The procedure uses a recursive depth-first search where the depth of the
    recursion (and thus the exhaustiveness of the search) is controlled by the
    parameter 'search_depth'.

    The pseudocode below describes the algorithm of
    'best_extension_by_limited_search'. The worst-case complexity of this
    algorithm is O(N*N^search_depth/search_depth). When serch_depth >= N, then
    the complexity of greedy_search is O(N!).

    procedure best_extension_by_limited_search(
      pplan in,             // in, partial plan of tables-joined-so-far
      pplan_cost,           // in, cost of pplan
      remaining_tables,     // in, set of tables not referenced in pplan
      best_plan_so_far,     // in/out, best plan found so far
      best_plan_so_far_cost,// in/out, cost of best_plan_so_far
      search_depth)         // in, maximum size of the plans being considered
    {
      for each table T from remaining_tables
      {
        // Calculate the cost of using table T as above
        cost = complex-series-of-calculations;

        // Add the cost to the cost so far.
        pplan_cost+= cost;

        if (pplan_cost >= best_plan_so_far_cost)
          // pplan_cost already too great, stop search
          continue;

        pplan= expand pplan by best_access_method;
        remaining_tables= remaining_tables - table T;
        if (remaining_tables is not an empty set
            and
            search_depth > 1)
        {
          best_extension_by_limited_search(pplan, pplan_cost,
                                           remaining_tables,
                                           best_plan_so_far,
                                           best_plan_so_far_cost,
                                           search_depth - 1);
        }
        else
        {
          best_plan_so_far_cost= pplan_cost;
          best_plan_so_far= pplan;
        }
      }
    }
unknown's avatar
unknown committed
4193

unknown's avatar
af  
unknown committed
4194 4195 4196 4197 4198 4199 4200 4201
  IMPLEMENTATION
    When 'best_extension_by_limited_search' is called for the first time,
    'join->best_read' must be set to the largest possible value (e.g. DBL_MAX).
    The actual implementation provides a way to optionally use pruning
    heuristic (controlled by the parameter 'prune_level') to reduce the search
    space by skipping some partial plans.
    The parameter 'search_depth' provides control over the recursion
    depth, and thus the size of the resulting optimal plan.
unknown's avatar
unknown committed
4202

unknown's avatar
af  
unknown committed
4203 4204 4205
  RETURN
    None
*/
unknown's avatar
unknown committed
4206 4207

static void
unknown's avatar
af  
unknown committed
4208 4209 4210 4211 4212 4213 4214
best_extension_by_limited_search(JOIN      *join,
                                 table_map remaining_tables,
                                 uint      idx,
                                 double    record_count,
                                 double    read_time,
                                 uint      search_depth,
                                 uint      prune_level)
unknown's avatar
unknown committed
4215
{
unknown's avatar
af  
unknown committed
4216 4217 4218
  THD *thd= join->thd;
  if (thd->killed)  // Abort
    return;
unknown's avatar
unknown committed
4219

unknown's avatar
af  
unknown committed
4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233
  DBUG_ENTER("best_extension_by_limited_search");

  /* 
     'join' is a partial plan with lower cost than the best plan so far,
     so continue expanding it further with the tables in 'remaining_tables'.
  */
  JOIN_TAB *s;
  double best_record_count= DBL_MAX;
  double best_read_time=    DBL_MAX;

  DBUG_EXECUTE("opt",
               print_plan(join, read_time, record_count, idx, "part_plan"););

  for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
unknown's avatar
unknown committed
4234
  {
unknown's avatar
af  
unknown committed
4235 4236 4237 4238
    table_map real_table_bit= s->table->map;
    if ((remaining_tables & real_table_bit) && !(remaining_tables & s->dependent))
    {
      double current_record_count, current_read_time;
unknown's avatar
unknown committed
4239

unknown's avatar
af  
unknown committed
4240 4241 4242 4243 4244
      /* Find the best access method from 's' to the current partial plan */
      best_access_path(join, s, thd, remaining_tables, idx, record_count, read_time);
      /* Compute the cost of extending the plan with 's' */
      current_record_count= record_count * join->positions[idx].records_read;
      current_read_time=    read_time + join->positions[idx].read_time;
unknown's avatar
unknown committed
4245

unknown's avatar
af  
unknown committed
4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311
      /* Expand only partial plans with lower cost than the best QEP so far */
      if ((current_read_time +
           current_record_count / (double) TIME_FOR_COMPARE) >= join->best_read)
      {
        DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx,
                                       "prune_by_cost"););
        continue;
      }

      /*
        Prune some less promising partial plans. This heuristic may miss
        the optimal QEPs, thus it results in a non-exhaustive search.
      */
      if (prune_level == 1)
      {
        if (best_record_count > current_record_count ||
            best_read_time > current_read_time ||
            idx == join->const_tables &&  // 's' is the first table in the QEP
            s->table == join->sort_by_table)
        {
          if (best_record_count >= current_record_count &&
              best_read_time >= current_read_time &&
              /* TODO: What is the reasoning behind this condition? */
              (!(s->key_dependent & remaining_tables) ||
               join->positions[idx].records_read < 2.0))
          {
            best_record_count= current_record_count;
            best_read_time=    current_read_time;
          }
        }
        else
        {
          DBUG_EXECUTE("opt", print_plan(join, read_time, record_count, idx,
                                         "pruned_by_heuristic"););
          continue;
        }
      }

      if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) )
      { /* Recursively expand the current partial plan */
        swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
        best_extension_by_limited_search(join,
                                         remaining_tables & ~real_table_bit,
                                         idx + 1,
                                         current_record_count,
                                         current_read_time,
                                         search_depth - 1,
                                         prune_level);
        if (thd->killed)
          DBUG_VOID_RETURN;
        swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
      }
      else
      { /*
          'join' is either the best partial QEP with 'search_depth' relations,
          or the best complete QEP so far, whichever is smaller.
        */
        current_read_time+= current_record_count / (double) TIME_FOR_COMPARE;
        if (join->sort_by_table &&
            join->sort_by_table != join->positions[join->const_tables].table->table)
          /* We have to make a temp table */
          current_read_time+= current_record_count;
        if ((search_depth == 1) || (current_read_time < join->best_read))
        {
          memcpy((gptr) join->best_positions, (gptr) join->positions,
                 sizeof(POSITION) * (idx + 1));
unknown's avatar
unknown committed
4312
          join->best_read= current_read_time - 0.001;
unknown's avatar
af  
unknown committed
4313 4314 4315 4316 4317 4318
        }
        DBUG_EXECUTE("opt",
                     print_plan(join, current_read_time, current_record_count, idx, "full_plan"););
      }
    }
  }
unknown's avatar
unknown committed
4319 4320 4321 4322
  DBUG_VOID_RETURN;
}


unknown's avatar
af  
unknown committed
4323 4324 4325 4326
/*
  TODO: this function is here only temporarily until 'greedy_search' is
  tested and accepted.
*/
unknown's avatar
unknown committed
4327 4328 4329 4330
static void
find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
	  double read_time)
{
4331
  ha_rows rec;
unknown's avatar
unknown committed
4332
  double tmp;
unknown's avatar
unknown committed
4333
  THD *thd= join->thd;
unknown's avatar
unknown committed
4334 4335 4336 4337 4338 4339 4340 4341

  if (!rest_tables)
  {
    DBUG_PRINT("best",("read_time: %g  record_count: %g",read_time,
		       record_count));

    read_time+=record_count/(double) TIME_FOR_COMPARE;
    if (join->sort_by_table &&
unknown's avatar
af  
unknown committed
4342 4343
	join->sort_by_table !=
	join->positions[join->const_tables].table->table)
unknown's avatar
unknown committed
4344 4345 4346 4347 4348
      read_time+=record_count;			// We have to make a temp table
    if (read_time < join->best_read)
    {
      memcpy((gptr) join->best_positions,(gptr) join->positions,
	     sizeof(POSITION)*idx);
unknown's avatar
unknown committed
4349
      join->best_read= read_time - 0.001;
unknown's avatar
unknown committed
4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365
    }
    return;
  }
  if (read_time+record_count/(double) TIME_FOR_COMPARE >= join->best_read)
    return;					/* Found better before */

  JOIN_TAB *s;
  double best_record_count=DBL_MAX,best_read_time=DBL_MAX;
  for (JOIN_TAB **pos=join->best_ref+idx ; (s=*pos) ; pos++)
  {
    table_map real_table_bit=s->table->map;
    if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent))
    {
      double best,best_time,records;
      best=best_time=records=DBL_MAX;
      KEYUSE *best_key=0;
4366
      uint best_max_key_part=0;
4367
      my_bool found_constraint= 0;
unknown's avatar
unknown committed
4368 4369 4370 4371 4372 4373

      if (s->keyuse)
      {						/* Use key if possible */
	TABLE *table=s->table;
	KEYUSE *keyuse,*start_key=0;
	double best_records=DBL_MAX;
4374
	uint max_key_part=0;
unknown's avatar
unknown committed
4375 4376

	/* Test how we can use keys */
4377
	rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE;  // Assumed records/key
unknown's avatar
unknown committed
4378 4379
	for (keyuse=s->keyuse ; keyuse->table == table ;)
	{
4380
	  key_part_map found_part=0;
unknown's avatar
unknown committed
4381 4382 4383 4384
	  table_map found_ref=0;
	  uint key=keyuse->key;
	  KEY *keyinfo=table->key_info+key;
          bool ft_key=(keyuse->keypart == FT_KEYPART);
4385
	  uint found_ref_or_null= 0;
unknown's avatar
unknown committed
4386

4387
	  /* Calculate how many key segments of the current key we can use */
unknown's avatar
unknown committed
4388 4389 4390 4391
	  start_key=keyuse;
	  do
	  {
            uint keypart=keyuse->keypart;
unknown's avatar
af  
unknown committed
4392 4393
            table_map best_part_found_ref= 0;
            double best_prev_record_reads= DBL_MAX;
unknown's avatar
unknown committed
4394 4395
	    do
	    {
4396 4397 4398 4399
	      if (!(rest_tables & keyuse->used_tables) &&
		  !(found_ref_or_null & keyuse->optimize))
	      {
		found_part|=keyuse->keypart_map;
unknown's avatar
af  
unknown committed
4400 4401 4402 4403 4404 4405 4406 4407
                double tmp= prev_record_reads(join,
					      (found_ref |
					       keyuse->used_tables));
                if (tmp < best_prev_record_reads)
                {
                  best_part_found_ref= keyuse->used_tables;
                  best_prev_record_reads= tmp;
                }
4408 4409
		if (rec > keyuse->ref_table_rows)
		  rec= keyuse->ref_table_rows;
unknown's avatar
af  
unknown committed
4410 4411
		/*
		  If there is one 'key_column IS NULL' expression, we can
4412
		  use this ref_or_null optimisation of this field
unknown's avatar
af  
unknown committed
4413 4414 4415
		*/
		found_ref_or_null|= (keyuse->optimize &
				     KEY_OPTIMIZE_REF_OR_NULL);
unknown's avatar
unknown committed
4416 4417 4418 4419
              }
	      keyuse++;
	    } while (keyuse->table == table && keyuse->key == key &&
		     keyuse->keypart == keypart);
unknown's avatar
af  
unknown committed
4420
	    found_ref|= best_part_found_ref;
unknown's avatar
unknown committed
4421 4422 4423
	  } while (keyuse->table == table && keyuse->key == key);

	  /*
4424
	    Assume that that each key matches a proportional part of table.
unknown's avatar
unknown committed
4425 4426 4427
	  */
          if (!found_part && !ft_key)
	    continue;				// Nothing usable found
4428 4429
	  if (rec < MATCHING_ROWS_IN_OTHER_TABLE)
	    rec= MATCHING_ROWS_IN_OTHER_TABLE;	// Fix for small tables
unknown's avatar
unknown committed
4430 4431

          /*
4432
	    ft-keys require special treatment
unknown's avatar
unknown committed
4433 4434 4435 4436
          */
          if (ft_key)
          {
            /*
4437 4438
	      Really, there should be records=0.0 (yes!)
	      but 1.0 would be probably safer
unknown's avatar
unknown committed
4439 4440 4441 4442 4443 4444
            */
            tmp=prev_record_reads(join,found_ref);
            records=1.0;
          }
          else
          {
4445
	  found_constraint= 1;
unknown's avatar
unknown committed
4446
	  /*
4447
	    Check if we found full key
unknown's avatar
unknown committed
4448
	  */
4449 4450
	  if (found_part == PREV_BITS(uint,keyinfo->key_parts) &&
	      !found_ref_or_null)
unknown's avatar
unknown committed
4451
	  {				/* use eq key */
4452
	    max_key_part= (uint) ~0;
4453 4454
	    if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
				   HA_END_SPACE_KEY)) == HA_NOSAME)
unknown's avatar
unknown committed
4455 4456 4457 4458 4459 4460
	    {
	      tmp=prev_record_reads(join,found_ref);
	      records=1.0;
	    }
	    else
	    {
4461 4462
	      if (!found_ref)
	      {					// We found a const key
4463
		if (table->quick_keys.is_set(key))
unknown's avatar
unknown committed
4464 4465
		  records= (double) table->quick_rows[key];
		else
unknown's avatar
unknown committed
4466 4467 4468 4469
		{
		  /* quick_range couldn't use key! */
		  records= (double) s->records/rec;
		}
unknown's avatar
unknown committed
4470 4471 4472 4473 4474 4475 4476 4477
	      }
	      else
	      {
		if (!(records=keyinfo->rec_per_key[keyinfo->key_parts-1]))
		{				// Prefere longer keys
		  records=
		    ((double) s->records / (double) rec *
		     (1.0 +
4478 4479
		      ((double) (table->s->max_key_length-keyinfo->key_length) /
		       (double) table->s->max_key_length)));
unknown's avatar
unknown committed
4480 4481 4482 4483
		  if (records < 2.0)
		    records=2.0;		// Can't be as good as a unique
		}
	      }
4484 4485 4486
	      /* Limit the number of matched rows */
	      tmp= records;
	      set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
4487
	      if (table->used_keys.is_set(key))
unknown's avatar
unknown committed
4488 4489 4490
	      {
		/* we can use only index tree */
		uint keys_per_block= table->file->block_size/2/
unknown's avatar
unknown committed
4491
		  (keyinfo->key_length+table->file->ref_length)+1;
4492
		tmp=record_count*(tmp+keys_per_block-1)/keys_per_block;
unknown's avatar
unknown committed
4493 4494
	      }
	      else
4495
		tmp=record_count*min(tmp,s->worst_seeks);
unknown's avatar
unknown committed
4496 4497 4498 4499 4500
	    }
	  }
	  else
	  {
	    /*
4501 4502 4503
	      Use as much key-parts as possible and a uniq key is better
	      than a not unique key
	      Set tmp to (previous record count) * (records / combination)
unknown's avatar
unknown committed
4504
	    */
4505
	    if ((found_part & 1) &&
4506
		(!(table->file->index_flags(key,0,0) & HA_ONLY_WHOLE_INDEX) ||
4507
		 found_part == PREV_BITS(uint,keyinfo->key_parts)))
unknown's avatar
unknown committed
4508
	    {
4509
	      max_key_part=max_part_bit(found_part);
4510 4511 4512 4513
	      /*
		Check if quick_range could determinate how many rows we
		will match
	      */
4514
	      if (table->quick_keys.is_set(key) &&
unknown's avatar
af  
unknown committed
4515
		  table->quick_key_parts[key] == max_key_part)
unknown's avatar
unknown committed
4516 4517 4518 4519 4520 4521 4522 4523 4524
		tmp=records= (double) table->quick_rows[key];
	      else
	      {
		/* Check if we have statistic about the distribution */
		if ((records=keyinfo->rec_per_key[max_key_part-1]))
		  tmp=records;
		else
		{
		  /*
4525
		    Assume that the first key part matches 1% of the file
unknown's avatar
unknown committed
4526
		    and that the whole key matches 10 (duplicates) or 1
4527 4528 4529 4530 4531
		    (unique) records.
		    Assume also that more key matches proportionally more
		    records
		    This gives the formula:
		    records= (x * (b-a) + a*c-b)/(c-1)
4532

4533 4534 4535 4536
		    b = records matched by whole key
		    a = records matched by first key part (10% of all records?)
		    c = number of key parts in key
		    x = used key parts (1 <= x <= c)
unknown's avatar
unknown committed
4537 4538
		  */
		  double rec_per_key;
4539 4540 4541
                  rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1] ?
		    (double) keyinfo->rec_per_key[keyinfo->key_parts-1] :
		    (double) s->records/rec+1;   
unknown's avatar
unknown committed
4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555
		  if (!s->records)
		    tmp=0;
		  else if (rec_per_key/(double) s->records >= 0.01)
		    tmp=rec_per_key;
		  else
		  {
		    double a=s->records*0.01;
		    tmp=(max_key_part * (rec_per_key - a) +
			 a*keyinfo->key_parts - rec_per_key)/
		      (keyinfo->key_parts-1);
		    set_if_bigger(tmp,1.0);
		  }
		  records=(ulong) tmp;
		}
unknown's avatar
af  
unknown committed
4556 4557 4558 4559 4560 4561 4562 4563 4564
		/*
		  If quick_select was used on a part of this key, we know
		  the maximum number of rows that the key can match.
		*/
		if (table->quick_keys.is_set(key) &&
		    table->quick_key_parts[key] <= max_key_part &&
		    records > (double) table->quick_rows[key])
		  tmp= records= (double) table->quick_rows[key];
		else if (found_ref_or_null)
4565 4566 4567 4568 4569
		{
		  /* We need to do two key searches to find key */
		  tmp*= 2.0;
		  records*= 2.0;
		}
unknown's avatar
unknown committed
4570
	      }
4571 4572
	      /* Limit the number of matched rows */
	      set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
4573
	      if (table->used_keys.is_set(key))
unknown's avatar
unknown committed
4574 4575 4576
	      {
		/* we can use only index tree */
		uint keys_per_block= table->file->block_size/2/
unknown's avatar
unknown committed
4577
		  (keyinfo->key_length+table->file->ref_length)+1;
unknown's avatar
unknown committed
4578 4579 4580 4581 4582 4583 4584 4585
		tmp=record_count*(tmp+keys_per_block-1)/keys_per_block;
	      }
	      else
		tmp=record_count*min(tmp,s->worst_seeks);
	    }
	    else
	      tmp=best_time;			// Do nothing
	  }
4586
          } /* not ft_key */
unknown's avatar
unknown committed
4587 4588 4589 4590 4591 4592
	  if (tmp < best_time - records/(double) TIME_FOR_COMPARE)
	  {
	    best_time=tmp + records/(double) TIME_FOR_COMPARE;
	    best=tmp;
	    best_records=records;
	    best_key=start_key;
4593
	    best_max_key_part=max_key_part;
unknown's avatar
unknown committed
4594 4595 4596 4597
	  }
	}
	records=best_records;
      }
4598 4599 4600 4601

      /*
	Don't test table scan if it can't be better.
	Prefer key lookup if we would use the same key for scanning.
4602 4603 4604 4605 4606

	Don't do a table scan on InnoDB tables, if we can read the used
	parts of the row from any of the used index.
	This is because table scans uses index and we would not win
	anything by using a table scan.
4607 4608 4609
      */
      if ((records >= s->found_records || best > s->read_time) &&
	  !(s->quick && best_key && s->quick->index == best_key->key &&
4610
	    best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
4611
	  !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
4612
	    ! s->table->used_keys.is_clear_all() && best_key) &&
4613
	  !(s->table->force_index && best_key))
unknown's avatar
unknown committed
4614
      {						// Check full join
4615 4616 4617 4618 4619 4620 4621 4622 4623 4624
        ha_rows rnd_records= s->found_records;
        /*
          If there is a restriction on the table, assume that 25% of the
          rows can be skipped on next part.
          This is to force tables that this table depends on before this
          table
        */
        if (found_constraint)
          rnd_records-= rnd_records/4;

4625 4626 4627 4628 4629 4630
        /*
          Range optimizer never proposes a RANGE if it isn't better
          than FULL: so if RANGE is present, it's always preferred to FULL.
          Here we estimate its cost.
        */
        if (s->quick)
4631
        {
4632 4633 4634 4635 4636
          /*
            For each record we:
             - read record range through 'quick'
             - skip rows which does not satisfy WHERE constraints
           */
4637
          tmp= record_count *
4638 4639
               (s->quick->read_time +
               (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE);
4640 4641 4642
        }
        else
        {
4643 4644
          /* Estimate cost of reading table. */
          tmp= s->table->file->scan_time();
4645
          if (s->table->map  & join->outer_join)      // Can't use join cache
4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670
          {
            /*
              For each record we have to:
              - read the whole table record 
              - skip rows which does not satisfy join condition
            */
            tmp= record_count *
                 (tmp +     
                 (s->records - rnd_records)/(double) TIME_FOR_COMPARE);
          }
          else
          {
            /* We read the table as many times as join buffer becomes full. */
            tmp*= (1.0 + floor((double) cache_record_length(join,idx) *
                               record_count /
                               (double) thd->variables.join_buff_size));
            /* 
              We don't make full cartesian product between rows in the scanned
              table and existing records because we skip all rows from the
              scanned table, which does not satisfy join condition when 
              we read the table (see flush_cached_records for details). Here we
              take into account cost to read and skip these records.
            */
            tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
          }
4671
        }
4672

4673
        /*
4674
          We estimate the cost of evaluating WHERE clause for found records
4675
          as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus
4676
          tmp give us total cost of using TABLE SCAN
unknown's avatar
unknown committed
4677
        */
unknown's avatar
unknown committed
4678
	if (best == DBL_MAX ||
4679
	    (tmp  + record_count/(double) TIME_FOR_COMPARE*rnd_records <
unknown's avatar
unknown committed
4680 4681
	     best + record_count/(double) TIME_FOR_COMPARE*records))
	{
4682 4683 4684 4685
	  /*
	    If the table has a range (s->quick is set) make_join_select()
	    will ensure that this will be used
	  */
unknown's avatar
unknown committed
4686
	  best=tmp;
4687
	  records= rows2double(rnd_records);
unknown's avatar
unknown committed
4688 4689 4690
	  best_key=0;
	}
      }
4691
      join->positions[idx].records_read= records;
unknown's avatar
unknown committed
4692 4693 4694
      join->positions[idx].key=best_key;
      join->positions[idx].table= s;
      if (!best_key && idx == join->const_tables &&
unknown's avatar
unknown committed
4695
	  s->table == join->sort_by_table &&
4696
	  join->unit->select_limit_cnt >= records)
unknown's avatar
unknown committed
4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715
	join->sort_by_table= (TABLE*) 1;	// Must use temporary table

     /*
	Go to the next level only if there hasn't been a better key on
	this level! This will cut down the search for a lot simple cases!
       */
      double current_record_count=record_count*records;
      double current_read_time=read_time+best;
      if (best_record_count > current_record_count ||
	  best_read_time > current_read_time ||
	  idx == join->const_tables && s->table == join->sort_by_table)
      {
	if (best_record_count >= current_record_count &&
	    best_read_time >= current_read_time &&
	    (!(s->key_dependent & rest_tables) || records < 2.0))
	{
	  best_record_count=current_record_count;
	  best_read_time=current_read_time;
	}
unknown's avatar
af  
unknown committed
4716
	swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
unknown's avatar
unknown committed
4717 4718
	find_best(join,rest_tables & ~real_table_bit,idx+1,
		  current_record_count,current_read_time);
unknown's avatar
unknown committed
4719 4720
        if (thd->killed)
          return;
unknown's avatar
af  
unknown committed
4721
	swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
unknown's avatar
unknown committed
4722 4723 4724 4725 4726 4727 4728 4729 4730
      }
      if (join->select_options & SELECT_STRAIGHT_JOIN)
	break;				// Don't test all combinations
    }
  }
}


/*
4731
  Find how much space the prevous read not const tables takes in cache
unknown's avatar
unknown committed
4732 4733
*/

4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753
static void calc_used_field_length(THD *thd, JOIN_TAB *join_tab)
{
  uint null_fields,blobs,fields,rec_length;
  null_fields=blobs=fields=rec_length=0;

  Field **f_ptr,*field;
  for (f_ptr=join_tab->table->field ; (field= *f_ptr) ; f_ptr++)
  {
    if (field->query_id == thd->query_id)
    {
      uint flags=field->flags;
      fields++;
      rec_length+=field->pack_length();
      if (flags & BLOB_FLAG)
	blobs++;
      if (!(flags & NOT_NULL_FLAG))
	null_fields++;
    }
  }
  if (null_fields)
4754
    rec_length+=(join_tab->table->s->null_fields+7)/8;
4755 4756 4757 4758 4759
  if (join_tab->table->maybe_null)
    rec_length+=sizeof(my_bool);
  if (blobs)
  {
    uint blob_length=(uint) (join_tab->table->file->mean_rec_length-
4760
			     (join_tab->table->s->reclength- rec_length));
4761 4762 4763 4764 4765 4766 4767 4768
    rec_length+=(uint) max(4,blob_length);
  }
  join_tab->used_fields=fields;
  join_tab->used_fieldlength=rec_length;
  join_tab->used_blobs=blobs;
}


unknown's avatar
unknown committed
4769 4770 4771
static uint
cache_record_length(JOIN *join,uint idx)
{
4772
  uint length=0;
unknown's avatar
unknown committed
4773
  JOIN_TAB **pos,**end;
4774
  THD *thd=join->thd;
unknown's avatar
unknown committed
4775 4776 4777 4778 4779 4780

  for (pos=join->best_ref+join->const_tables,end=join->best_ref+idx ;
       pos != end ;
       pos++)
  {
    JOIN_TAB *join_tab= *pos;
4781 4782
    if (!join_tab->used_fieldlength)		/* Not calced yet */
      calc_used_field_length(thd, join_tab);
unknown's avatar
unknown committed
4783 4784 4785 4786 4787 4788 4789 4790 4791 4792
    length+=join_tab->used_fieldlength;
  }
  return length;
}


static double
prev_record_reads(JOIN *join,table_map found_ref)
{
  double found=1.0;
unknown's avatar
unknown committed
4793
  found_ref&= ~OUTER_REF_TABLE_BIT;
unknown's avatar
unknown committed
4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806
  for (POSITION *pos=join->positions ; found_ref ; pos++)
  {
    if (pos->table->table->map & found_ref)
    {
      found_ref&= ~pos->table->table->map;
      found*=pos->records_read;
    }
  }
  return found;
}


/*****************************************************************************
4807
  Set up join struct according to best position.
unknown's avatar
unknown committed
4808 4809 4810 4811 4812
*****************************************************************************/

static bool
get_best_combination(JOIN *join)
{
4813
  uint i,tablenr;
unknown's avatar
unknown committed
4814 4815 4816 4817
  table_map used_tables;
  JOIN_TAB *join_tab,*j;
  KEYUSE *keyuse;
  uint table_count;
4818
  THD *thd=join->thd;
unknown's avatar
unknown committed
4819
  DBUG_ENTER("get_best_combination");
unknown's avatar
unknown committed
4820 4821 4822

  table_count=join->tables;
  if (!(join->join_tab=join_tab=
4823
	(JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*table_count)))
unknown's avatar
unknown committed
4824
    DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
4825 4826 4827

  join->full_join=0;

unknown's avatar
unknown committed
4828
  used_tables= OUTER_REF_TABLE_BIT;		// Outer row is already read
unknown's avatar
unknown committed
4829 4830 4831 4832 4833 4834 4835
  for (j=join_tab, tablenr=0 ; tablenr < table_count ; tablenr++,j++)
  {
    TABLE *form;
    *j= *join->best_positions[tablenr].table;
    form=join->table[tablenr]=j->table;
    used_tables|= form->map;
    form->reginfo.join_tab=j;
unknown's avatar
unknown committed
4836
    if (!*j->on_expr_ref)
unknown's avatar
unknown committed
4837
      form->reginfo.not_exists_optimize=0;	// Only with LEFT JOIN
unknown's avatar
unknown committed
4838
    DBUG_PRINT("info",("type: %d", j->type));
4839 4840 4841 4842 4843
    if (j->type == JT_CONST)
      continue;					// Handled in make_join_stat..

    j->ref.key = -1;
    j->ref.key_parts=0;
unknown's avatar
unknown committed
4844 4845 4846

    if (j->type == JT_SYSTEM)
      continue;
4847
    if (j->keys.is_clear_all() || !(keyuse= join->best_positions[tablenr].key))
unknown's avatar
unknown committed
4848 4849 4850 4851 4852
    {
      j->type=JT_ALL;
      if (tablenr != join->const_tables)
	join->full_join=1;
    }
4853
    else if (create_ref_for_key(join, j, keyuse, used_tables))
unknown's avatar
unknown committed
4854
      DBUG_RETURN(TRUE);                        // Something went wrong
4855
  }
unknown's avatar
unknown committed
4856

4857 4858 4859
  for (i=0 ; i < table_count ; i++)
    join->map2table[join->join_tab[i].table->tablenr]=join->join_tab+i;
  update_depend_map(join);
unknown's avatar
unknown committed
4860
  DBUG_RETURN(0);
4861
}
4862

unknown's avatar
unknown committed
4863

4864 4865 4866 4867 4868 4869 4870 4871 4872
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
			       table_map used_tables)
{
  KEYUSE *keyuse=org_keyuse;
  bool ftkey=(keyuse->keypart == FT_KEYPART);
  THD  *thd= join->thd;
  uint keyparts,length,key;
  TABLE *table;
  KEY *keyinfo;
unknown's avatar
unknown committed
4873
  DBUG_ENTER("create_ref_for_key");
4874

4875
  /*  Use best key from find_best */
4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890
  table=j->table;
  key=keyuse->key;
  keyinfo=table->key_info+key;

  if (ftkey)
  {
    Item_func_match *ifm=(Item_func_match *)keyuse->val;

    length=0;
    keyparts=1;
    ifm->join_key=1;
  }
  else
  {
    keyparts=length=0;
4891 4892 4893 4894 4895 4896
    uint found_part_ref_or_null= 0;
    /*
      Calculate length for the used key
      Stop if there is a missing key part or when we find second key_part
      with KEY_OPTIMIZE_REF_OR_NULL
    */
4897 4898
    do
    {
4899
      if (!(~used_tables & keyuse->used_tables))
unknown's avatar
unknown committed
4900
      {
4901 4902
	if (keyparts == keyuse->keypart &&
	    !(found_part_ref_or_null & keyuse->optimize))
unknown's avatar
unknown committed
4903
	{
4904
	  keyparts++;
4905 4906
	  length+= keyinfo->key_part[keyuse->keypart].store_length;
	  found_part_ref_or_null|= keyuse->optimize;
unknown's avatar
unknown committed
4907 4908
	}
      }
4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922
      keyuse++;
    } while (keyuse->table == table && keyuse->key == key);
  } /* not ftkey */

  /* set up fieldref */
  keyinfo=table->key_info+key;
  j->ref.key_parts=keyparts;
  j->ref.key_length=length;
  j->ref.key=(int) key;
  if (!(j->ref.key_buff= (byte*) thd->calloc(ALIGN_SIZE(length)*2)) ||
      !(j->ref.key_copy= (store_key**) thd->alloc((sizeof(store_key*) *
						   (keyparts+1)))) ||
      !(j->ref.items=    (Item**) thd->alloc(sizeof(Item*)*keyparts)))
  {
unknown's avatar
unknown committed
4923
    DBUG_RETURN(TRUE);
4924 4925 4926
  }
  j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length);
  j->ref.key_err=1;
4927
  j->ref.null_rejecting= 0;
4928 4929
  keyuse=org_keyuse;

4930 4931
  store_key **ref_key= j->ref.key_copy;
  byte *key_buff=j->ref.key_buff, *null_ref_key= 0;
4932
  bool keyuse_uses_no_tables= TRUE;
4933 4934 4935 4936
  if (ftkey)
  {
    j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
    if (keyuse->used_tables)
unknown's avatar
unknown committed
4937
      DBUG_RETURN(TRUE);                        // not supported yet. SerG
4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951

    j->type=JT_FT;
  }
  else
  {
    uint i;
    for (i=0 ; i < keyparts ; keyuse++,i++)
    {
      while (keyuse->keypart != i ||
	     ((~used_tables) & keyuse->used_tables))
	keyuse++;				/* Skip other parts */

      uint maybe_null= test(keyinfo->key_part[i].null_bit);
      j->ref.items[i]=keyuse->val;		// Save for cond removal
4952 4953
      if (keyuse->null_rejecting) 
        j->ref.null_rejecting |= 1 << i;
4954
      keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables;
4955 4956 4957
      if (!keyuse->used_tables &&
	  !(join->select_options & SELECT_DESCRIBE))
      {					// Compare against constant
unknown's avatar
unknown committed
4958 4959 4960 4961
	store_key_item tmp(thd, keyinfo->key_part[i].field,
                           (char*)key_buff + maybe_null,
                           maybe_null ?  (char*) key_buff : 0,
                           keyinfo->key_part[i].length, keyuse->val);
4962
	if (thd->is_fatal_error)
unknown's avatar
unknown committed
4963
	  DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
4964
	tmp.copy();
unknown's avatar
unknown committed
4965 4966
      }
      else
4967 4968 4969 4970
	*ref_key++= get_store_key(thd,
				  keyuse,join->const_table_map,
				  &keyinfo->key_part[i],
				  (char*) key_buff,maybe_null);
unknown's avatar
af  
unknown committed
4971
      /*
4972
	Remember if we are going to use REF_OR_NULL
unknown's avatar
af  
unknown committed
4973 4974 4975 4976
	But only if field _really_ can be null i.e. we force JT_REF
	instead of JT_REF_OR_NULL in case if field can't be null
      */
      if ((keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) && maybe_null)
4977
	null_ref_key= key_buff;
4978
      key_buff+=keyinfo->key_part[i].store_length;
unknown's avatar
unknown committed
4979
    }
4980 4981
  } /* not ftkey */
  *ref_key=0;				// end_marker
4982
  if (j->type == JT_FT)
unknown's avatar
unknown committed
4983
    DBUG_RETURN(0);
4984 4985
  if (j->type == JT_CONST)
    j->table->const_table= 1;
4986
  else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
unknown's avatar
unknown committed
4987
			       HA_END_SPACE_KEY)) != HA_NOSAME) ||
unknown's avatar
unknown committed
4988
	   keyparts != keyinfo->key_parts || null_ref_key)
4989 4990 4991
  {
    /* Must read with repeat */
    j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
unknown's avatar
af  
unknown committed
4992
    j->ref.null_ref_key= null_ref_key;
4993
  }
4994
  else if (keyuse_uses_no_tables)
4995
  {
4996 4997 4998 4999 5000 5001 5002 5003
    /*
      This happen if we are using a constant expression in the ON part
      of an LEFT JOIN.
      SELECT * FROM a LEFT JOIN b ON b.key=30
      Here we should not mark the table as a 'const' as a field may
      have a 'normal' value or a NULL value.
    */
    j->type=JT_CONST;
unknown's avatar
unknown committed
5004
  }
5005 5006
  else
    j->type=JT_EQ_REF;
unknown's avatar
unknown committed
5007
  DBUG_RETURN(0);
unknown's avatar
unknown committed
5008 5009 5010
}


5011

unknown's avatar
unknown committed
5012
static store_key *
unknown's avatar
unknown committed
5013 5014
get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
	      KEY_PART_INFO *key_part, char *key_buff, uint maybe_null)
unknown's avatar
unknown committed
5015 5016 5017
{
  if (!((~used_tables) & keyuse->used_tables))		// if const item
  {
unknown's avatar
unknown committed
5018 5019
    return new store_key_const_item(thd,
				    key_part->field,
unknown's avatar
unknown committed
5020 5021 5022 5023 5024 5025
				    key_buff + maybe_null,
				    maybe_null ? key_buff : 0,
				    key_part->length,
				    keyuse->val);
  }
  else if (keyuse->val->type() == Item::FIELD_ITEM)
unknown's avatar
unknown committed
5026 5027
    return new store_key_field(thd,
			       key_part->field,
unknown's avatar
unknown committed
5028 5029 5030 5031 5032
			       key_buff + maybe_null,
			       maybe_null ? key_buff : 0,
			       key_part->length,
			       ((Item_field*) keyuse->val)->field,
			       keyuse->val->full_name());
unknown's avatar
unknown committed
5033 5034
  return new store_key_item(thd,
			    key_part->field,
unknown's avatar
unknown committed
5035 5036 5037 5038 5039 5040 5041
			    key_buff + maybe_null,
			    maybe_null ? key_buff : 0,
			    key_part->length,
			    keyuse->val);
}

/*
5042 5043
  This function is only called for const items on fields which are keys
  returns 1 if there was some conversion made when the field was stored.
unknown's avatar
unknown committed
5044 5045 5046 5047 5048
*/

bool
store_val_in_field(Field *field,Item *item)
{
5049
  bool error;
unknown's avatar
unknown committed
5050
  THD *thd= field->table->in_use;
5051
  ha_rows cuted_fields=thd->cuted_fields;
unknown's avatar
af  
unknown committed
5052 5053 5054 5055 5056 5057
  /*
    we should restore old value of count_cuted_fields because
    store_val_in_field can be called from mysql_insert 
    with select_insert, which make count_cuted_fields= 1
   */
  enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
5058
  thd->count_cuted_fields= CHECK_FIELD_WARN;
5059
  error= item->save_in_field(field, 1);
unknown's avatar
af  
unknown committed
5060
  thd->count_cuted_fields= old_count_cuted_fields;
5061
  return error || cuted_fields != thd->cuted_fields;
unknown's avatar
unknown committed
5062 5063 5064 5065 5066 5067 5068 5069
}


static bool
make_simple_join(JOIN *join,TABLE *tmp_table)
{
  TABLE **tableptr;
  JOIN_TAB *join_tab;
unknown's avatar
unknown committed
5070
  DBUG_ENTER("make_simple_join");
unknown's avatar
unknown committed
5071

5072 5073
  if (!(tableptr=(TABLE**) join->thd->alloc(sizeof(TABLE*))) ||
      !(join_tab=(JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
unknown's avatar
unknown committed
5074
    DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
5075 5076 5077 5078 5079
  join->join_tab=join_tab;
  join->table=tableptr; tableptr[0]=tmp_table;
  join->tables=1;
  join->const_tables=0;
  join->const_table_map=0;
unknown's avatar
unknown committed
5080 5081 5082
  join->tmp_table_param.field_count= join->tmp_table_param.sum_func_count=
    join->tmp_table_param.func_count=0;
  join->tmp_table_param.copy_field=join->tmp_table_param.copy_field_end=0;
unknown's avatar
unknown committed
5083
  join->first_record=join->sort_and_group=0;
unknown's avatar
unknown committed
5084
  join->send_records=(ha_rows) 0;
unknown's avatar
unknown committed
5085
  join->group=0;
unknown's avatar
unknown committed
5086
  join->row_limit=join->unit->select_limit_cnt;
unknown's avatar
unknown committed
5087
  join->do_send_rows = (join->row_limit) ? 1 : 0;
unknown's avatar
unknown committed
5088

unknown's avatar
unknown committed
5089
  join_tab->cache.buff=0;			/* No caching */
unknown's avatar
unknown committed
5090 5091 5092 5093 5094
  join_tab->table=tmp_table;
  join_tab->select=0;
  join_tab->select_cond=0;
  join_tab->quick=0;
  join_tab->type= JT_ALL;			/* Map through all records */
unknown's avatar
unknown committed
5095
  join_tab->keys.init(~0);                      /* test everything in quick */
unknown's avatar
unknown committed
5096
  join_tab->info=0;
unknown's avatar
unknown committed
5097
  join_tab->on_expr_ref=0;
5098 5099
  join_tab->last_inner= 0;
  join_tab->first_unmatched= 0;
unknown's avatar
unknown committed
5100
  join_tab->ref.key = -1;
unknown's avatar
unknown committed
5101 5102
  join_tab->not_used_in_distinct=0;
  join_tab->read_first_record= join_init_read_record;
5103
  join_tab->join=join;
unknown's avatar
unknown committed
5104
  join_tab->ref.key_parts= 0;
unknown's avatar
unknown committed
5105
  bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
unknown's avatar
unknown committed
5106 5107
  tmp_table->status=0;
  tmp_table->null_row=0;
unknown's avatar
unknown committed
5108
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
5109 5110 5111
}


5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181
inline void add_cond_and_fix(Item **e1, Item *e2)
{
  if (*e1)
  {
    Item *res;
    if ((res= new Item_cond_and(*e1, e2)))
    {
      *e1= res;
      res->quick_fix_field();
    }
  }
  else
    *e1= e2;
}


/*
  Add to join_tab->select_cond[i] "table.field IS NOT NULL" conditions we've
  inferred from ref/eq_ref access performed.

  SYNOPSIS
    add_not_null_conds()
      join  Join to process

  NOTES
    This function is a part of "Early NULL-values filtering for ref access"
    optimization.

    Example of this optimization:
      For query SELECT * FROM t1,t2 WHERE t2.key=t1.field
      and plan " any-access(t1), ref(t2.key=t1.field) "
      add "t1.field IS NOT NULL" to t1's table condition.
    Description of the optimization:
    
      We look through equalities choosen to perform ref/eq_ref access,
      pick equalities that have form "tbl.part_of_key = othertbl.field"
      (where othertbl is a non-const table and othertbl.field may be NULL)
      and add them to conditions on correspoding tables (othertbl in this
      example).
      
      This optimization doesn't affect the choices that ref, range, or join
      optimizer make. This was intentional because this was added after 4.1
      was GA.
      
    Implementation overview
      1. update_ref_and_keys() accumulates info about null-rejecting
         predicates in in KEY_FIELD::null_rejecting
      1.1 add_key_part saves these to KEYUSE.
      2. create_ref_for_key copies them to TABLE_REF.
      3. add_not_null_conds adds "x IS NOT NULL" to join_tab->select_cond of
         appropiate JOIN_TAB members.
*/

static void add_not_null_conds(JOIN *join)
{
  DBUG_ENTER("add_not_null_conds");
  for (uint i=join->const_tables ; i < join->tables ; i++)
  {
    JOIN_TAB *tab=join->join_tab+i;
    if ((tab->type == JT_REF || tab->type == JT_REF_OR_NULL) &&
         !tab->table->maybe_null)
    {
      for (uint keypart= 0; keypart < tab->ref.key_parts; keypart++)
      {
        if (tab->ref.null_rejecting & (1 << keypart))
        {
          Item *item= tab->ref.items[keypart];
          DBUG_ASSERT(item->type() == Item::FIELD_ITEM);
          Item_field *not_null_item= (Item_field*)item;
          JOIN_TAB *referred_tab= not_null_item->field->table->reginfo.join_tab;
5182 5183
          Item_func_isnotnull *notnull;
          if (!(notnull= new Item_func_isnotnull(not_null_item)))
5184 5185
            DBUG_VOID_RETURN;

5186 5187
          notnull->quick_fix_field();
          DBUG_EXECUTE("where",print_where(notnull,
unknown's avatar
unknown committed
5188
                                           referred_tab->table->alias););
5189
          add_cond_and_fix(&referred_tab->select_cond, notnull);
5190 5191 5192 5193 5194 5195 5196
        }
      }
    }
  }
  DBUG_VOID_RETURN;
}

5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226
/*
  Build a predicate guarded by match variables for embedding outer joins

  SYNOPSIS
    add_found_match_trig_cond()
    tab       the first inner table for most nested outer join
    cond      the predicate to be guarded
    root_tab  the first inner table to stop

  DESCRIPTION
    The function recursively adds guards for predicate cond
    assending from tab to the first inner table  next embedding
    nested outer join and so on until it reaches root_tab
    (root_tab can be 0).

  RETURN VALUE
    pointer to the guarded predicate, if success
    0, otherwise
*/ 

static COND*
add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab)
{
  COND *tmp;
  if (tab == root_tab || !cond)
    return cond;
  if ((tmp= add_found_match_trig_cond(tab->first_upper, cond, root_tab)))
  {
    tmp= new Item_func_trig_cond(tmp, &tab->found);
  }
unknown's avatar
unknown committed
5227
  if (tmp)
unknown's avatar
unknown committed
5228
    tmp->quick_fix_field();
5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251
  return tmp;
}


/*
   Fill in outer join related info for the execution plan structure

  SYNOPSIS
    make_outerjoin_info()
    join - reference to the info fully describing the query

  DESCRIPTION
    For each outer join operation left after simplification of the
    original query the function set up the following pointers in the linear
    structure join->join_tab representing the selected execution plan.
    The first inner table t0 for the operation is set to refer to the last
    inner table tk through the field t0->last_inner.
    Any inner table ti for the operation are set to refer to the first
    inner table ti->first_inner.
    The first inner table t0 for the operation is set to refer to the
    first inner table of the embedding outer join operation, if there is any,
    through the field t0->first_upper.
    The on expression for the outer join operation is attached to the
unknown's avatar
unknown committed
5252
    corresponding first inner table through the field t0->on_expr_ref.
5253 5254 5255
    Here ti are structures of the JOIN_TAB type.

  EXAMPLE
unknown's avatar
unknown committed
5256
    For the query: 
5257 5258 5259 5260 5261 5262 5263 5264 5265
      SELECT * FROM t1
                    LEFT JOIN
                    (t2, t3 LEFT JOIN t4 ON t3.a=t4.a)
                    ON (t1.a=t2.a AND t1.b=t3.b)
        WHERE t1.c > 5,
    given the execution plan with the table order t1,t2,t3,t4
    is selected, the following references will be set;
    t4->last_inner=[t4], t4->first_inner=[t4], t4->first_upper=[t2]
    t2->last_inner=[t4], t2->first_inner=t3->first_inner=[t2],
unknown's avatar
unknown committed
5266 5267
    on expression (t1.a=t2.a AND t1.b=t3.b) will be attached to 
    *t2->on_expr_ref, while t3.a=t4.a will be attached to *t4->on_expr_ref.
5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278
            
  NOTES
    The function assumes that the simplification procedure has been
    already applied to the join query (see simplify_joins).
    This function can be called only after the execution plan
    has been chosen.
*/
 
static void
make_outerjoin_info(JOIN *join)
{
5279
  DBUG_ENTER("make_outerjoin_info");
5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294
  for (uint i=join->const_tables ; i < join->tables ; i++)
  {
    JOIN_TAB *tab=join->join_tab+i;
    TABLE *table=tab->table;
    TABLE_LIST *tbl= table->pos_in_table_list;
    TABLE_LIST *embedding= tbl->embedding;

    if (tbl->outer_join)
    {
      /* 
        Table tab is the only one inner table for outer join.
        (Like table t4 for the table reference t3 LEFT JOIN t4 ON t3.a=t4.a
        is in the query above.)
      */
      tab->last_inner= tab->first_inner= tab;
unknown's avatar
unknown committed
5295 5296
      tab->on_expr_ref= &tbl->on_expr;
      tab->cond_equal= tbl->cond_equal;
5297 5298 5299
      if (embedding)
        tab->first_upper= embedding->nested_join->first_nested;
    }    
unknown's avatar
unknown committed
5300
    for ( ; embedding ; embedding= embedding->embedding)
5301 5302 5303 5304 5305 5306 5307 5308 5309
    {
      NESTED_JOIN *nested_join= embedding->nested_join;
      if (!nested_join->counter)
      {
        /* 
          Table tab is the first inner table for nested_join.
          Save reference to it in the nested join structure.
        */ 
        nested_join->first_nested= tab;
unknown's avatar
unknown committed
5310 5311
        tab->on_expr_ref= &embedding->on_expr;
        tab->cond_equal= tbl->cond_equal;
5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322
        if (embedding->embedding)
          tab->first_upper= embedding->embedding->nested_join->first_nested;
      }
      if (!tab->first_inner)  
        tab->first_inner= nested_join->first_nested;
      if (++nested_join->counter < nested_join->join_list.elements)
        break;
      /* Table tab is the last inner table for nested join. */
      nested_join->first_nested->last_inner= tab;
    }
  }
5323
  DBUG_VOID_RETURN;
5324 5325 5326
}


unknown's avatar
unknown committed
5327 5328 5329
static bool
make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
{
unknown's avatar
unknown committed
5330
  THD *thd= join->thd;
unknown's avatar
unknown committed
5331 5332 5333
  DBUG_ENTER("make_join_select");
  if (select)
  {
5334
    add_not_null_conds(join);
unknown's avatar
unknown committed
5335
    table_map used_tables;
5336
    if (cond)                /* Because of QUICK_GROUP_MIN_MAX_SELECT */
unknown's avatar
unknown committed
5337
    {                        /* there may be a select without a cond. */    
5338 5339 5340
      if (join->tables > 1)
        cond->update_used_tables();		// Tablenr may have changed
      if (join->const_tables == join->tables &&
unknown's avatar
unknown committed
5341 5342
	  thd->lex->current_select->master_unit() ==
	  &thd->lex->unit)		// not upper level SELECT
5343 5344 5345
        join->const_table_map|=RAND_TABLE_BIT;
      {						// Check const tables
        COND *const_cond=
5346
	  make_cond_for_table(cond,join->const_table_map,(table_map) 0);
5347
        DBUG_EXECUTE("where",print_where(const_cond,"constants"););
5348 5349 5350
        for (JOIN_TAB *tab= join->join_tab+join->const_tables;
             tab < join->join_tab+join->tables ; tab++)
        {
5351
          if (*tab->on_expr_ref)
5352 5353
          {
            JOIN_TAB *cond_tab= tab->first_inner;
5354
            COND *tmp= make_cond_for_table(*tab->on_expr_ref,
5355
                                           join->const_table_map,
5356
                                         (  table_map) 0);
5357 5358 5359 5360 5361 5362 5363
            if (!tmp)
              continue;
            tmp= new Item_func_trig_cond(tmp, &cond_tab->not_null_compl);
            if (!tmp)
              DBUG_RETURN(1);
            tmp->quick_fix_field();
            cond_tab->select_cond= !cond_tab->select_cond ? tmp :
5364
	                            new Item_cond_and(cond_tab->select_cond,tmp);
5365
            if (!cond_tab->select_cond)
5366
	      DBUG_RETURN(1);
5367
            cond_tab->select_cond->quick_fix_field();
5368
          }       
5369
        }
5370 5371
        if (const_cond && !const_cond->val_int())
        {
5372
	  DBUG_PRINT("info",("Found impossible WHERE condition"));
unknown's avatar
unknown committed
5373
	  DBUG_RETURN(1);	 // Impossible const condition
5374
        }
5375
      }
unknown's avatar
unknown committed
5376
    }
unknown's avatar
unknown committed
5377 5378
    used_tables=((select->const_tables=join->const_table_map) |
		 OUTER_REF_TABLE_BIT | RAND_TABLE_BIT);
unknown's avatar
unknown committed
5379 5380 5381
    for (uint i=join->const_tables ; i < join->tables ; i++)
    {
      JOIN_TAB *tab=join->join_tab+i;
5382
      JOIN_TAB *first_inner_tab= tab->first_inner; 
unknown's avatar
unknown committed
5383
      table_map current_map= tab->table->map;
5384
      bool use_quick_range=0;
unknown's avatar
unknown committed
5385 5386 5387 5388
      /*
	Following force including random expression in last table condition.
	It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
      */
5389
      if (i == join->tables-1)
unknown's avatar
unknown committed
5390
	current_map|= OUTER_REF_TABLE_BIT | RAND_TABLE_BIT;
unknown's avatar
unknown committed
5391
      used_tables|=current_map;
5392 5393

      if (tab->type == JT_REF && tab->quick &&
unknown's avatar
unknown committed
5394
	  (uint) tab->ref.key == tab->quick->index &&
5395 5396 5397 5398 5399 5400
	  tab->ref.key_length < tab->quick->max_used_key_length)
      {
	/* Range uses longer key;  Use this instead of ref on key */
	tab->type=JT_ALL;
	use_quick_range=1;
	tab->use_quick=1;
unknown's avatar
af  
unknown committed
5401
        tab->ref.key= -1;
5402
	tab->ref.key_parts=0;		// Don't use ref key.
5403
	join->best_positions[i].records_read= rows2double(tab->quick->records);
5404 5405
      }

5406 5407 5408 5409
      COND *tmp= NULL;
      if (cond)
        tmp= make_cond_for_table(cond,used_tables,current_map);
      if (cond && !tmp && tab->quick)
5410
      {						// Outer join
5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427
        if (tab->type != JT_ALL)
        {
          /*
            Don't use the quick method
            We come here in the case where we have 'key=constant' and
            the test is removed by make_cond_for_table()
          */
          delete tab->quick;
          tab->quick= 0;
        }
        else
        {
          /*
            Hack to handle the case where we only refer to a table
            in the ON part of an OUTER JOIN. In this case we want the code
            below to check if we should use 'quick' instead.
          */
5428
          DBUG_PRINT("info", ("Item_int"));
5429
          tmp= new Item_int((longlong) 1,1);	// Always true
5430
          DBUG_PRINT("info", ("Item_int 0x%lx", (ulong)tmp));
5431 5432
        }

5433
      }
5434
      if (tmp || !cond)
unknown's avatar
unknown committed
5435
      {
5436
	DBUG_EXECUTE("where",print_where(tmp,tab->table->alias););
unknown's avatar
unknown committed
5437
	SQL_SELECT *sel=tab->select=(SQL_SELECT*)
unknown's avatar
unknown committed
5438
	  thd->memdup((gptr) select, sizeof(SQL_SELECT));
unknown's avatar
unknown committed
5439 5440
	if (!sel)
	  DBUG_RETURN(1);			// End of memory
5441 5442 5443 5444 5445
        /*
          If tab is an inner table of an outer join operation,
          add a match guard to the pushed down predicate.
          The guard will turn the predicate on only after
          the first match for outer tables is encountered.
5446
	*/        
5447
        if (cond)
unknown's avatar
unknown committed
5448 5449
        {
          /*
5450 5451 5452 5453 5454 5455
            Because of QUICK_GROUP_MIN_MAX_SELECT there may be a select without
            a cond, so neutralize the hack above.
          */
          if (!(tmp= add_found_match_trig_cond(first_inner_tab, tmp, 0)))
            DBUG_RETURN(1);
          tab->select_cond=sel->cond=tmp;
unknown's avatar
unknown committed
5456
	  if (thd->variables.engine_condition_pushdown)
5457 5458 5459 5460 5461 5462
          {
            tab->table->file->pushed_cond= NULL;
	    /* Push condition to handler */
            if (!tab->table->file->cond_push(tmp))
              tab->table->file->pushed_cond= tmp;
          }
5463 5464 5465
        }
        else
          tab->select_cond= sel->cond= NULL;
5466

unknown's avatar
unknown committed
5467
	sel->head=tab->table;
unknown's avatar
unknown committed
5468
	DBUG_EXECUTE("where",print_where(tmp,tab->table->alias););
unknown's avatar
unknown committed
5469 5470
	if (tab->quick)
	{
5471 5472
	  /* Use quick key read if it's a constant and it's not used
	     with key reading */
5473
	  if (tab->needed_reg.is_clear_all() && tab->type != JT_EQ_REF
5474
	      && tab->type != JT_FT && (tab->type != JT_REF ||
unknown's avatar
unknown committed
5475
               (uint) tab->ref.key == tab->quick->index))
unknown's avatar
unknown committed
5476 5477
	  {
	    sel->quick=tab->quick;		// Use value from get_quick_...
5478 5479
	    sel->quick_keys.clear_all();
	    sel->needed_reg.clear_all();
unknown's avatar
unknown committed
5480 5481 5482 5483 5484 5485 5486 5487 5488 5489
	  }
	  else
	  {
	    delete tab->quick;
	  }
	  tab->quick=0;
	}
	uint ref_key=(uint) sel->head->reginfo.join_tab->ref.key+1;
	if (i == join->const_tables && ref_key)
	{
5490 5491
	  if (!tab->const_keys.is_clear_all() &&
              tab->table->reginfo.impossible_range)
unknown's avatar
unknown committed
5492 5493
	    DBUG_RETURN(1);
	}
5494
	else if (tab->type == JT_ALL && ! use_quick_range)
unknown's avatar
unknown committed
5495
	{
5496
	  if (!tab->const_keys.is_clear_all() &&
unknown's avatar
unknown committed
5497 5498 5499 5500
	      tab->table->reginfo.impossible_range)
	    DBUG_RETURN(1);				// Impossible range
	  /*
	    We plan to scan all rows.
5501 5502 5503
	    Check again if we should use an index.
	    We could have used an column from a previous table in
	    the index if we are using limit and this is the first table
unknown's avatar
unknown committed
5504 5505
	  */

5506 5507
	  if (cond &&
              (!tab->keys.is_subset(tab->const_keys) && i > 0) ||
5508 5509
	      (!tab->const_keys.is_clear_all() && i == join->const_tables &&
	       join->unit->select_limit_cnt <
5510
	       join->best_positions[i].records_read &&
5511
	       !(join->select_options & OPTION_FOUND_ROWS)))
unknown's avatar
unknown committed
5512
	  {
5513 5514
	    /* Join with outer join condition */
	    COND *orig_cond=sel->cond;
unknown's avatar
unknown committed
5515
	    sel->cond= and_conds(sel->cond, *tab->on_expr_ref);
5516 5517 5518 5519 5520 5521 5522 5523

	    /*
              We can't call sel->cond->fix_fields,
              as it will break tab->on_expr if it's AND condition
              (fix_fields currently removes extra AND/OR levels).
              Yet attributes of the just built condition are not needed.
              Thus we call sel->cond->quick_fix_field for safety.
	    */
unknown's avatar
af  
unknown committed
5524
	    if (sel->cond && !sel->cond->fixed)
5525 5526
	      sel->cond->quick_fix_field();

unknown's avatar
unknown committed
5527
	    if (sel->test_quick_select(thd, tab->keys,
unknown's avatar
unknown committed
5528
				       used_tables & ~ current_map,
5529 5530 5531
				       (join->select_options &
					OPTION_FOUND_ROWS ?
					HA_POS_ERROR :
5532
					join->unit->select_limit_cnt)) < 0)
unknown's avatar
unknown committed
5533 5534 5535 5536 5537
            {
	      /*
		Before reporting "Impossible WHERE" for the whole query
		we have to check isn't it only "impossible ON" instead
	      */
5538
              sel->cond=orig_cond;
unknown's avatar
unknown committed
5539
              if (!*tab->on_expr_ref ||
unknown's avatar
unknown committed
5540
                  sel->test_quick_select(thd, tab->keys,
5541 5542 5543 5544
                                         used_tables & ~ current_map,
                                         (join->select_options &
                                          OPTION_FOUND_ROWS ?
                                          HA_POS_ERROR :
unknown's avatar
unknown committed
5545 5546
                                          join->unit->select_limit_cnt)) < 0)
		DBUG_RETURN(1);			// Impossible WHERE
5547 5548 5549 5550
            }
            else
	      sel->cond=orig_cond;

5551 5552 5553
	    /* Fix for EXPLAIN */
	    if (sel->quick)
	      join->best_positions[i].records_read= sel->quick->records;
unknown's avatar
unknown committed
5554 5555 5556 5557
	  }
	  else
	  {
	    sel->needed_reg=tab->needed_reg;
5558
	    sel->quick_keys.clear_all();
unknown's avatar
unknown committed
5559
	  }
5560 5561
	  if (!sel->quick_keys.is_subset(tab->checked_keys) ||
              !sel->needed_reg.is_subset(tab->checked_keys))
unknown's avatar
unknown committed
5562
	  {
5563 5564 5565 5566
	    tab->keys=sel->quick_keys;
            tab->keys.merge(sel->needed_reg);
	    tab->use_quick= (!sel->needed_reg.is_clear_all() &&
			     (select->quick_keys.is_clear_all() ||
unknown's avatar
unknown committed
5567 5568 5569
			      (select->quick &&
			       (select->quick->records >= 100L)))) ?
	      2 : 1;
unknown's avatar
unknown committed
5570
	    sel->read_tables= used_tables & ~current_map;
unknown's avatar
unknown committed
5571 5572 5573
	  }
	  if (i != join->const_tables && tab->use_quick != 2)
	  {					/* Read with cache */
5574 5575
	    if (cond &&
                (tmp=make_cond_for_table(cond,
unknown's avatar
unknown committed
5576 5577 5578 5579 5580
					 join->const_table_map |
					 current_map,
					 current_map)))
	    {
	      DBUG_EXECUTE("where",print_where(tmp,"cache"););
5581
	      tab->cache.select=(SQL_SELECT*)
unknown's avatar
unknown committed
5582
		thd->memdup((gptr) sel, sizeof(SQL_SELECT));
unknown's avatar
unknown committed
5583 5584
	      tab->cache.select->cond=tmp;
	      tab->cache.select->read_tables=join->const_table_map;
unknown's avatar
unknown committed
5585
	      if (thd->variables.engine_condition_pushdown &&
5586 5587 5588 5589 5590 5591
		  (!tab->table->file->pushed_cond))
              {
		/* Push condition to handler */
		if (!tab->table->file->cond_push(tmp))
                  tab->table->file->pushed_cond= tmp;
              }
unknown's avatar
unknown committed
5592 5593 5594
	    }
	  }
	}
unknown's avatar
unknown committed
5595
      }
5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611
      
      /* 
        Push down all predicates from on expressions.
        Each of these predicated are guarded by a variable
        that turns if off just before null complemented row for
        outer joins is formed. Thus, the predicates from an
        'on expression' are guaranteed not to be checked for
        the null complemented row.
      */ 
      JOIN_TAB *last_tab= tab;
      while (first_inner_tab && first_inner_tab->last_inner == last_tab)
      {  
        /* 
          Table tab is the last inner table of an outer join.
          An on expression is always attached to it.
	*/     
unknown's avatar
unknown committed
5612
        COND *on_expr= *first_inner_tab->on_expr_ref;
5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634

        table_map used_tables= join->const_table_map |
		               OUTER_REF_TABLE_BIT | RAND_TABLE_BIT;
	for (tab= join->join_tab+join->const_tables; tab <= last_tab ; tab++)
        {
          current_map= tab->table->map;
          used_tables|= current_map;
          COND *tmp= make_cond_for_table(on_expr, used_tables, current_map);
          if (tmp)
          {
            JOIN_TAB *cond_tab= tab < first_inner_tab ? first_inner_tab : tab;
            /*
              First add the guards for match variables of
              all embedding outer join operations.
	    */
            if (!(tmp= add_found_match_trig_cond(cond_tab->first_inner,
                                                 tmp, first_inner_tab)))
              DBUG_RETURN(1);
            /* 
              Now add the guard turning the predicate off for 
              the null complemented row.
	    */ 
5635
            DBUG_PRINT("info", ("Item_func_trig_cond"));
5636 5637
            tmp= new Item_func_trig_cond(tmp, 
                                         &first_inner_tab->not_null_compl);
5638
            DBUG_PRINT("info", ("Item_func_trig_cond 0x%lx", (ulong) tmp));
unknown's avatar
unknown committed
5639 5640
            if (tmp)
              tmp->quick_fix_field();
5641
	    /* Add the predicate to other pushed down predicates */
5642
            DBUG_PRINT("info", ("Item_cond_and"));
5643 5644
            cond_tab->select_cond= !cond_tab->select_cond ? tmp :
	                          new Item_cond_and(cond_tab->select_cond,tmp);
5645 5646
            DBUG_PRINT("info", ("Item_cond_and 0x%lx",
                                (ulong)cond_tab->select_cond));
5647 5648
            if (!cond_tab->select_cond)
	      DBUG_RETURN(1);
unknown's avatar
unknown committed
5649
            cond_tab->select_cond->quick_fix_field();
5650 5651 5652
          }              
        }
        first_inner_tab= first_inner_tab->first_upper;       
unknown's avatar
unknown committed
5653 5654 5655 5656 5657 5658 5659
      }
    }
  }
  DBUG_RETURN(0);
}

static void
5660
make_join_readinfo(JOIN *join, uint options)
unknown's avatar
unknown committed
5661 5662
{
  uint i;
5663

unknown's avatar
af  
unknown committed
5664
  bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
unknown's avatar
unknown committed
5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683
  DBUG_ENTER("make_join_readinfo");

  for (i=join->const_tables ; i < join->tables ; i++)
  {
    JOIN_TAB *tab=join->join_tab+i;
    TABLE *table=tab->table;
    tab->read_record.table= table;
    tab->read_record.file=table->file;
    tab->next_select=sub_select;		/* normal select */
    switch (tab->type) {
    case JT_SYSTEM:				// Only happens with left join
      table->status=STATUS_NO_RECORD;
      tab->read_first_record= join_read_system;
      tab->read_record.read_record= join_no_more_records;
      break;
    case JT_CONST:				// Only happens with left join
      table->status=STATUS_NO_RECORD;
      tab->read_first_record= join_read_const;
      tab->read_record.read_record= join_no_more_records;
unknown's avatar
af  
unknown committed
5684 5685 5686 5687 5688 5689
      if (table->used_keys.is_set(tab->ref.key) &&
          !table->no_keyread)
      {
        table->key_read=1;
        table->file->extra(HA_EXTRA_KEYREAD);
      }
unknown's avatar
unknown committed
5690 5691 5692
      break;
    case JT_EQ_REF:
      table->status=STATUS_NO_RECORD;
5693 5694 5695 5696 5697
      if (tab->select)
      {
	delete tab->select->quick;
	tab->select->quick=0;
      }
unknown's avatar
unknown committed
5698 5699 5700 5701
      delete tab->quick;
      tab->quick=0;
      tab->read_first_record= join_read_key;
      tab->read_record.read_record= join_no_more_records;
5702
      if (table->used_keys.is_set(tab->ref.key) &&
unknown's avatar
unknown committed
5703
	  !table->no_keyread)
unknown's avatar
unknown committed
5704 5705 5706 5707 5708
      {
	table->key_read=1;
	table->file->extra(HA_EXTRA_KEYREAD);
      }
      break;
5709
    case JT_REF_OR_NULL:
unknown's avatar
unknown committed
5710 5711
    case JT_REF:
      table->status=STATUS_NO_RECORD;
5712 5713 5714 5715 5716
      if (tab->select)
      {
	delete tab->select->quick;
	tab->select->quick=0;
      }
unknown's avatar
unknown committed
5717 5718
      delete tab->quick;
      tab->quick=0;
5719
      if (table->used_keys.is_set(tab->ref.key) &&
unknown's avatar
unknown committed
5720
	  !table->no_keyread)
unknown's avatar
unknown committed
5721 5722 5723 5724
      {
	table->key_read=1;
	table->file->extra(HA_EXTRA_KEYREAD);
      }
5725 5726 5727 5728 5729 5730 5731 5732 5733 5734
      if (tab->type == JT_REF)
      {
	tab->read_first_record= join_read_always_key;
	tab->read_record.read_record= join_read_next_same;
      }
      else
      {
	tab->read_first_record= join_read_always_key_or_null;
	tab->read_record.read_record= join_read_next_same_or_null;
      }
unknown's avatar
unknown committed
5735 5736 5737 5738 5739 5740 5741 5742
      break;
    case JT_FT:
      table->status=STATUS_NO_RECORD;
      tab->read_first_record= join_ft_read_first;
      tab->read_record.read_record= join_ft_read_next;
      break;
    case JT_ALL:
      /*
5743
	If previous table use cache
unknown's avatar
unknown committed
5744 5745
      */
      table->status=STATUS_NO_RECORD;
unknown's avatar
unknown committed
5746
      if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
5747
          tab->use_quick != 2 && !tab->first_inner)
unknown's avatar
unknown committed
5748 5749 5750 5751 5752 5753 5754 5755 5756 5757
      {
	if ((options & SELECT_DESCRIBE) ||
	    !join_init_cache(join->thd,join->join_tab+join->const_tables,
			     i-join->const_tables))
	{
	  tab[-1].next_select=sub_select_cache; /* Patch previous */
	}
      }
      /* These init changes read_record */
      if (tab->use_quick == 2)
5758
      {
5759
	join->thd->server_status|=SERVER_QUERY_NO_GOOD_INDEX_USED;
unknown's avatar
unknown committed
5760
	tab->read_first_record= join_init_quick_read_record;
unknown's avatar
af  
unknown committed
5761
	if (statistics)
5762 5763
	  statistic_increment(join->thd->status_var.select_range_check_count,
			      &LOCK_status);
5764
      }
unknown's avatar
unknown committed
5765 5766 5767
      else
      {
	tab->read_first_record= join_init_read_record;
5768 5769 5770 5771
	if (i == join->const_tables)
	{
	  if (tab->select && tab->select->quick)
	  {
unknown's avatar
af  
unknown committed
5772
	    if (statistics)
5773 5774
	      statistic_increment(join->thd->status_var.select_range_count,
				  &LOCK_status);
5775 5776 5777
	  }
	  else
	  {
5778
	    join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
unknown's avatar
af  
unknown committed
5779
	    if (statistics)
5780 5781
	      statistic_increment(join->thd->status_var.select_scan_count,
				  &LOCK_status);
5782 5783 5784 5785 5786 5787
	  }
	}
	else
	{
	  if (tab->select && tab->select->quick)
	  {
unknown's avatar
af  
unknown committed
5788
	    if (statistics)
5789 5790
	      statistic_increment(join->thd->status_var.select_full_range_join_count,
				  &LOCK_status);
5791 5792 5793
	  }
	  else
	  {
5794
	    join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
unknown's avatar
af  
unknown committed
5795
	    if (statistics)
5796 5797
	      statistic_increment(join->thd->status_var.select_full_join_count,
				  &LOCK_status);
5798 5799
	  }
	}
unknown's avatar
unknown committed
5800
	if (!table->no_keyread)
unknown's avatar
unknown committed
5801
	{
unknown's avatar
unknown committed
5802
	  if (tab->select && tab->select->quick &&
5803
	      table->used_keys.is_set(tab->select->quick->index))
unknown's avatar
unknown committed
5804 5805 5806 5807
	  {
	    table->key_read=1;
	    table->file->extra(HA_EXTRA_KEYREAD);
	  }
unknown's avatar
af  
unknown committed
5808 5809
	  else if (!table->used_keys.is_clear_all() &&
		   !(tab->select && tab->select->quick))
unknown's avatar
unknown committed
5810
	  {					// Only read index tree
unknown's avatar
unknown committed
5811
	    tab->index=find_shortest_key(table, & table->used_keys);
5812
	    tab->read_first_record= join_read_first;
unknown's avatar
unknown committed
5813 5814
	    tab->type=JT_NEXT;		// Read with index_first / index_next
	  }
unknown's avatar
unknown committed
5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830
	}
      }
      break;
    default:
      DBUG_PRINT("error",("Table type %d found",tab->type)); /* purecov: deadcode */
      break;					/* purecov: deadcode */
    case JT_UNKNOWN:
    case JT_MAYBE_REF:
      abort();					/* purecov: deadcode */
    }
  }
  join->join_tab[join->tables-1].next_select=0; /* Set by do_select */
  DBUG_VOID_RETURN;
}


unknown's avatar
unknown committed
5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852
/*
  Give error if we some tables are done with a full join

  SYNOPSIS
    error_if_full_join()
    join		Join condition

  USAGE
   This is used by multi_table_update and multi_table_delete when running
   in safe mode

 RETURN VALUES
   0	ok
   1	Error (full join used)
*/

bool error_if_full_join(JOIN *join)
{
  for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
       tab < end;
       tab++)
  {
5853
    if (tab->type == JT_ALL && (!tab->select || !tab->select->quick))
unknown's avatar
unknown committed
5854
    {
unknown's avatar
unknown committed
5855 5856
      my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
                 ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
unknown's avatar
unknown committed
5857 5858 5859 5860 5861 5862 5863
      return(1);
    }
  }
  return(0);
}


unknown's avatar
af  
unknown committed
5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885
/*
  cleanup JOIN_TAB

  SYNOPSIS
    JOIN_TAB::cleanup()
*/

void JOIN_TAB::cleanup()
{
  delete select;
  select= 0;
  delete quick;
  quick= 0;
  x_free(cache.buff);
  cache.buff= 0;
  if (table)
  {
    if (table->key_read)
    {
      table->key_read= 0;
      table->file->extra(HA_EXTRA_NO_KEYREAD);
    }
unknown's avatar
unknown committed
5886
    table->file->ha_index_or_rnd_end();
unknown's avatar
af  
unknown committed
5887 5888 5889 5890 5891 5892 5893 5894 5895 5896
    /*
      We need to reset this for next select
      (Tested in part_of_refkey)
    */
    table->reginfo.join_tab= 0;
  }
  end_read_record(&read_record);
}


5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909
/*
  Free resources of given join

  SYNOPSIS
    JOIN::join_free()
    fill - true if we should free all resources, call with full==1 should be
           last, before it this function can be called with full==0

  NOTE: with subquery this function definitely will be called several times,
    but even for simple query it can be called several times.
*/
void
JOIN::join_free(bool full)
unknown's avatar
unknown committed
5910 5911
{
  JOIN_TAB *tab,*end;
unknown's avatar
unknown committed
5912
  DBUG_ENTER("JOIN::join_free");
unknown's avatar
unknown committed
5913

unknown's avatar
unknown committed
5914 5915 5916
  full= full || (!select_lex->uncacheable &&
                 !thd->lex->subqueries &&
                 !thd->lex->describe); // do not cleanup too early on EXPLAIN
unknown's avatar
unknown committed
5917

5918
  if (table)
unknown's avatar
unknown committed
5919
  {
5920 5921 5922 5923
    /*
      Only a sorted table may be cached.  This sorted table is always the
      first non const table in join->table
    */
5924
    if (tables > const_tables) // Test for not-const tables
unknown's avatar
unknown committed
5925
    {
5926 5927
      free_io_cache(table[const_tables]);
      filesort_free_buffers(table[const_tables]);
unknown's avatar
unknown committed
5928
    }
5929 5930 5931

    for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); unit;
         unit= unit->next_unit())
5932
    {
5933 5934 5935 5936 5937
      JOIN *join;
      for (SELECT_LEX *sl= unit->first_select_in_union(); sl;
           sl= sl->next_select())
        if ((join= sl->join))
          join->join_free(full);
5938
    }
5939 5940

    if (full)
unknown's avatar
unknown committed
5941
    {
5942
      for (tab= join_tab, end= tab+tables; tab != end; tab++)
unknown's avatar
af  
unknown committed
5943
	tab->cleanup();
5944
      table= 0;
unknown's avatar
unknown committed
5945
      tables= 0;
unknown's avatar
unknown committed
5946
    }
unknown's avatar
unknown committed
5947
    else
5948
    {
5949
      for (tab= join_tab, end= tab+tables; tab != end; tab++)
unknown's avatar
unknown committed
5950
      {
5951 5952
	if (tab->table)
	    tab->table->file->ha_index_or_rnd_end();
unknown's avatar
unknown committed
5953
      }
5954
    }
unknown's avatar
unknown committed
5955
  }
5956

5957 5958 5959 5960
  /*
    We are not using tables anymore
    Unlock all tables. We may be in an INSERT .... SELECT statement.
  */
unknown's avatar
unknown committed
5961
  if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK) &&
5962
      !select_lex->subquery_in_having)
unknown's avatar
unknown committed
5963
  {
5964 5965 5966 5967 5968 5969 5970
    // TODO: unlock tables even if the join isn't top level select in the tree
    if (select_lex == (thd->lex->unit.fake_select_lex ?
                       thd->lex->unit.fake_select_lex : &thd->lex->select_lex))
    {
      mysql_unlock_read_tables(thd, lock);        // Don't free join->lock
      lock=0;
    }
unknown's avatar
unknown committed
5971
  }
5972

5973 5974
  if (full)
  {
5975
    group_fields.delete_elements();
5976 5977 5978 5979
    /*
      We can't call delete_elements() on copy_funcs as this will cause
      problems in free_elements() as some of the elements are then deleted.
    */
unknown's avatar
unknown committed
5980
    tmp_table_param.copy_funcs.empty();
5981
    tmp_table_param.cleanup();
5982
  }
unknown's avatar
unknown committed
5983
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
5984 5985 5986 5987
}


/*****************************************************************************
5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000
  Remove the following expressions from ORDER BY and GROUP BY:
  Constant expressions
  Expression that only uses tables that are of type EQ_REF and the reference
  is in the ORDER list or if all refereed tables are of the above type.

  In the following, the X field can be removed:
  SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t1.a,t2.X
  SELECT * FROM t1,t2,t3 WHERE t1.a=t2.a AND t2.b=t3.b ORDER BY t1.a,t3.X

  These can't be optimized:
  SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t2.X,t1.a
  SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b ORDER BY t1.a,t2.c
  SELECT * FROM t1,t2 WHERE t1.a=t2.a ORDER BY t2.b,t1.a
unknown's avatar
unknown committed
6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024
*****************************************************************************/

static bool
eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab)
{
  if (tab->cached_eq_ref_table)			// If cached
    return tab->eq_ref_table;
  tab->cached_eq_ref_table=1;
  if (tab->type == JT_CONST)			// We can skip const tables
    return (tab->eq_ref_table=1);		/* purecov: inspected */
  if (tab->type != JT_EQ_REF)
    return (tab->eq_ref_table=0);		// We must use this
  Item **ref_item=tab->ref.items;
  Item **end=ref_item+tab->ref.key_parts;
  uint found=0;
  table_map map=tab->table->map;

  for (; ref_item != end ; ref_item++)
  {
    if (! (*ref_item)->const_item())
    {						// Not a const ref
      ORDER *order;
      for (order=start_order ; order ; order=order->next)
      {
6025
	if ((*ref_item)->eq(order->item[0],0))
unknown's avatar
unknown committed
6026 6027 6028 6029 6030
	  break;
      }
      if (order)
      {
	found++;
unknown's avatar
unknown committed
6031
	DBUG_ASSERT(!(order->used & map));
unknown's avatar
unknown committed
6032 6033 6034 6035 6036 6037 6038 6039
	order->used|=map;
	continue;				// Used in ORDER BY
      }
      if (!only_eq_ref_tables(join,start_order, (*ref_item)->used_tables()))
	return (tab->eq_ref_table=0);
    }
  }
  /* Check that there was no reference to table before sort order */
6040
  for (; found && start_order ; start_order=start_order->next)
unknown's avatar
unknown committed
6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057
  {
    if (start_order->used & map)
    {
      found--;
      continue;
    }
    if (start_order->depend_map & map)
      return (tab->eq_ref_table=0);
  }
  return tab->eq_ref_table=1;
}


static bool
only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables)
{
  if (specialflag &  SPECIAL_SAFE_MODE)
6058
    return 0;			// skip this optimize /* purecov: inspected */
unknown's avatar
unknown committed
6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073
  for (JOIN_TAB **tab=join->map2table ; tables ; tab++, tables>>=1)
  {
    if (tables & 1 && !eq_ref_table(join, order, *tab))
      return 0;
  }
  return 1;
}


/* Update the dependency map for the tables */

static void update_depend_map(JOIN *join)
{
  JOIN_TAB *join_tab=join->join_tab, *end=join_tab+join->tables;

6074
  for (; join_tab != end ; join_tab++)
unknown's avatar
unknown committed
6075 6076 6077 6078 6079 6080 6081
  {
    TABLE_REF *ref= &join_tab->ref;
    table_map depend_map=0;
    Item **item=ref->items;
    uint i;
    for (i=0 ; i < ref->key_parts ; i++,item++)
      depend_map|=(*item)->used_tables();
unknown's avatar
unknown committed
6082
    ref->depend_map=depend_map & ~OUTER_REF_TABLE_BIT;
6083
    depend_map&= ~OUTER_REF_TABLE_BIT;
6084
    for (JOIN_TAB **tab=join->map2table;
unknown's avatar
unknown committed
6085
	 depend_map ;
6086
	 tab++,depend_map>>=1 )
unknown's avatar
unknown committed
6087 6088
    {
      if (depend_map & 1)
6089
	ref->depend_map|=(*tab)->ref.depend_map;
unknown's avatar
unknown committed
6090 6091 6092 6093 6094 6095 6096 6097 6098
    }
  }
}


/* Update the dependency map for the sort order */

static void update_depend_map(JOIN *join, ORDER *order)
{
6099
  for (; order ; order=order->next)
unknown's avatar
unknown committed
6100 6101 6102 6103
  {
    table_map depend_map;
    order->item[0]->update_used_tables();
    order->depend_map=depend_map=order->item[0]->used_tables();
unknown's avatar
unknown committed
6104 6105
    // Not item_sum(), RAND() and no reference to table outside of sub select
    if (!(order->depend_map & (OUTER_REF_TABLE_BIT | RAND_TABLE_BIT)))
unknown's avatar
unknown committed
6106
    {
6107
      for (JOIN_TAB **tab=join->map2table;
unknown's avatar
unknown committed
6108
	   depend_map ;
6109
	   tab++, depend_map>>=1)
unknown's avatar
unknown committed
6110 6111
      {
	if (depend_map & 1)
6112
	  order->depend_map|=(*tab)->ref.depend_map;
unknown's avatar
unknown committed
6113 6114 6115 6116 6117 6118 6119
      }
    }
  }
}


/*
unknown's avatar
unknown committed
6120 6121
  simple_order is set to 1 if sort_order only uses fields from head table
  and the head table is not a LEFT JOIN table
unknown's avatar
unknown committed
6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134
*/

static ORDER *
remove_const(JOIN *join,ORDER *first_order, COND *cond, bool *simple_order)
{
  if (join->tables == join->const_tables)
    return 0;					// No need to sort
  DBUG_ENTER("remove_const");
  ORDER *order,**prev_ptr;
  table_map first_table= join->join_tab[join->const_tables].table->map;
  table_map not_const_tables= ~join->const_table_map;
  table_map ref;
  prev_ptr= &first_order;
unknown's avatar
unknown committed
6135
  *simple_order= *join->join_tab[join->const_tables].on_expr_ref ? 0 : 1;
unknown's avatar
unknown committed
6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147

  /* NOTE: A variable of not_const_tables ^ first_table; breaks gcc 2.7 */

  update_depend_map(join, first_order);
  for (order=first_order; order ; order=order->next)
  {
    table_map order_tables=order->item[0]->used_tables();
    if (order->item[0]->with_sum_func)
      *simple_order=0;				// Must do a temp table to sort
    else if (!(order_tables & not_const_tables))
    {
      DBUG_PRINT("info",("removing: %s", order->item[0]->full_name()));
unknown's avatar
unknown committed
6148
      continue;					// skip const item
unknown's avatar
unknown committed
6149 6150 6151
    }
    else
    {
unknown's avatar
unknown committed
6152
      if (order_tables & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163
	*simple_order=0;
      else
      {
	Item *comp_item=0;
	if (cond && const_expression_in_where(cond,order->item[0], &comp_item))
	{
	  DBUG_PRINT("info",("removing: %s", order->item[0]->full_name()));
	  continue;
	}
	if ((ref=order_tables & (not_const_tables ^ first_table)))
	{
6164
	  if (!(order_tables & first_table) && only_eq_ref_tables(join,first_order,ref))
unknown's avatar
unknown committed
6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182
	  {
	    DBUG_PRINT("info",("removing: %s", order->item[0]->full_name()));
	    continue;
	  }
	  *simple_order=0;			// Must do a temp table to sort
	}
      }
    }
    *prev_ptr= order;				// use this entry
    prev_ptr= &order->next;
  }
  *prev_ptr=0;
  if (!first_order)				// Nothing to sort/group
    *simple_order=1;
  DBUG_PRINT("exit",("simple_order: %d",(int) *simple_order));
  DBUG_RETURN(first_order);
}

6183

unknown's avatar
unknown committed
6184
static int
6185 6186
return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
		 List<Item> &fields, bool send_row, uint select_options,
unknown's avatar
unknown committed
6187 6188
		 const char *info, Item *having, Procedure *procedure,
		 SELECT_LEX_UNIT *unit)
unknown's avatar
unknown committed
6189 6190 6191 6192
{
  DBUG_ENTER("return_zero_rows");

  if (select_options & SELECT_DESCRIBE)
6193
  {
unknown's avatar
af  
unknown committed
6194
    select_describe(join, FALSE, FALSE, FALSE, info);
unknown's avatar
unknown committed
6195 6196
    DBUG_RETURN(0);
  }
unknown's avatar
unknown committed
6197

6198 6199
  join->join_free(0);

unknown's avatar
unknown committed
6200 6201
  if (send_row)
  {
6202
    for (TABLE_LIST *table= tables; table; table= table->next_leaf)
unknown's avatar
unknown committed
6203
      mark_as_null_row(table->table);		// All fields are NULL
6204
    if (having && having->val_int() == 0)
unknown's avatar
unknown committed
6205 6206
      send_row=0;
  }
6207 6208
  if (!(result->send_fields(fields,
                              Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)))
unknown's avatar
unknown committed
6209 6210
  {
    if (send_row)
unknown's avatar
unknown committed
6211 6212 6213 6214 6215
    {
      List_iterator_fast<Item> it(fields);
      Item *item;
      while ((item= it++))
	item->no_rows_in_result();
unknown's avatar
unknown committed
6216
      result->send_data(fields);
unknown's avatar
unknown committed
6217
    }
6218
    result->send_eof();				// Should be safe
unknown's avatar
unknown committed
6219
  }
6220 6221
  /* Update results for FOUND_ROWS */
  join->thd->limit_found_rows= join->thd->examined_row_count= 0;
unknown's avatar
unknown committed
6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232
  DBUG_RETURN(0);
}


static void clear_tables(JOIN *join)
{
  for (uint i=0 ; i < join->tables ; i++)
    mark_as_null_row(join->table[i]);		// All fields are NULL
}

/*****************************************************************************
6233 6234 6235 6236 6237 6238
  Make som simple condition optimization:
  If there is a test 'field = const' change all refs to 'field' to 'const'
  Remove all dummy tests 'item = item', 'const op const'.
  Remove all 'item is NULL', when item can never be null!
  item->marker should be 0 for all items on entry
  Return in cond_value FALSE if condition is impossible (1 = 2)
unknown's avatar
unknown committed
6239 6240 6241 6242
*****************************************************************************/

class COND_CMP :public ilink {
public:
unknown's avatar
unknown committed
6243 6244 6245 6246
  static void *operator new(size_t size)
  {
    return (void*) sql_alloc((uint) size);
  }
unknown's avatar
unknown committed
6247
  static void operator delete(void *ptr __attribute__((unused)),
unknown's avatar
unknown committed
6248 6249
                              size_t size __attribute__((unused)))
  { TRASH(ptr, size); }
unknown's avatar
unknown committed
6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262

  Item *and_level;
  Item_func *cmp_func;
  COND_CMP(Item *a,Item_func *b) :and_level(a),cmp_func(b) {}
};

#ifdef __GNUC__
template class I_List<COND_CMP>;
template class I_List_iterator<COND_CMP>;
template class List<Item_func_match>;
template class List_iterator<Item_func_match>;
#endif

6263 6264 6265 6266 6267 6268 6269 6270

/* 
  Find the multiple equality predicate containing a field
 
  SYNOPSIS
    find_item_equal()
    cond_equal          multiple equalities to search in
    field               field to look for
unknown's avatar
unknown committed
6271
    inherited_fl  :out  set up to TRUE if multiple equality is found
6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298
                        on upper levels (not on current level of cond_equal) 

  DESCRIPTION
    The function retrieves the multiple equalities accessed through
    the con_equal structure from current level and up looking for
    an equality containing field. It stops retrieval as soon as the equality
    is found and set up inherited_fl to TRUE if it's found on upper levels.

  RETURN
    Item_equal for the found multiple equality predicate if a success;
    NULL - otherwise.
*/

Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
                            bool *inherited_fl)
{
  Item_equal *item= 0;
  bool in_upper_level= FALSE;
  while (cond_equal)
  {
    List_iterator_fast<Item_equal> li(cond_equal->current_level);
    while ((item= li++))
    {
      if (item->contains(field))
        goto finish;
    }
    in_upper_level= TRUE;
unknown's avatar
unknown committed
6299
    cond_equal= cond_equal->upper_levels;
6300 6301 6302
  }
  in_upper_level= FALSE;
finish:
unknown's avatar
unknown committed
6303
  *inherited_fl= in_upper_level;
6304 6305
  return item;
}
unknown's avatar
unknown committed
6306

6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318
  
/* 
  Check whether an item is a simple equality predicate and if so
  create/find a multiple equality for this predicate

  SYNOPSIS
    check_equality()
    item       item to check
    cond_equal multiple equalities that must hold together with the predicate

  DESCRIPTION
    This function first checks whether an item is a simple equality i.e.
unknown's avatar
unknown committed
6319 6320
    the one that equates a field with another field or a constant
    (item=constant_item or item=field_item).
6321
    If this is the case the function looks a for a multiple equality
unknown's avatar
unknown committed
6322 6323 6324 6325 6326 6327 6328 6329 6330
    in the lists referenced directly or indirectly by cond_equal inferring
    the given simple equality. If it doesn't find any, it builds a multiple
    equality that covers the predicate, i.e. the predicate can be inferred
    from it.
    The built multiple equality could be obtained in such a way:
    create a binary  multiple equality equivalent to the predicate, then
    merge it, if possible, with one of old multiple equalities.
    This guarantees that the set of multiple equalities covering equality
    predicates will
6331 6332
    be minimal.

unknown's avatar
unknown committed
6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343
  EXAMPLE
    For the where condition
    WHERE a=b AND b=c AND
          (b=2 OR f=e)
    the check_equality will be called for the following equality
    predicates a=b, b=c, b=2 and f=e.
    For a=b it will be called with *cond_equal=(0,[]) and will transform
    *cond_equal into (0,[Item_equal(a,b)]). 
    For b=c it will be called with *cond_equal=(0,[Item_equal(a,b)])
    and will transform *cond_equal into CE=(0,[Item_equal(a,b,c)]).
    For b=2 it will be called with *cond_equal=(ptr(CE),[])
6344
    and will transform *cond_equal into (ptr(CE),[Item_equal(2,a,b,c)]).
unknown's avatar
unknown committed
6345
    For f=e it will be called with *cond_equal=(ptr(CE), [])
6346
    and will transform *cond_equal into (ptr(CE),[Item_equal(f,e)]).
unknown's avatar
unknown committed
6347

6348 6349 6350 6351
  NOTES
    Now only fields that have the same type defintions (verified by
    the Field::eq_def method) are placed to the same multiple equalities.
    Because of this some equality predicates are not eliminated and
unknown's avatar
unknown committed
6352
    can be used in the constant propagation procedure.
6353 6354 6355 6356 6357 6358
    We could weeken the equlity test as soon as at least one of the 
    equal fields is to be equal to a constant. It would require a 
    more complicated implementation: we would have to store, in
    general case, its own constant for each fields from the multiple
    equality. But at the same time it would allow us to get rid
    of constant propagation completely: it would be done by the call
unknown's avatar
unknown committed
6359
    to build_equal_items_for_cond.
6360 6361 6362 6363 6364 6365
    
  IMPLEMENTATION
    The implementation does not follow exactly the above rules to
    build a new multiple equality for the equality predicate.
    If it processes the equality of the form field1=field2, it
    looks for multiple equalities me1 containig field1 and me2 containing
unknown's avatar
unknown committed
6366
    field2. If only one of them is found the fuction expands it with
6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403
    the lacking field. If multiple equalities for both fields are
    found they are merged. If both searches fail a new multiple equality
    containing just field1 and field2 is added to the existing
    multiple equalities.
    If the function processes the predicate of the form field1=const,
    it looks for a multiple equality containing field1. If found, the 
    function checks the constant of the multiple equality. If the value
    is unknown, it is setup to const. Otherwise the value is compared with
    const and the evaluation of the equality predicate is performed.
    When expanding/merging equality predicates from the upper levels
    the function first copies them for the current level. It looks
    acceptable, as this happens rarely. The implementation without
    copying would be much more complicated.

  RETURN
    TRUE  - if the predicate is a simple equality predicate
    FALSE - otherwise
*/

static bool check_equality(Item *item, COND_EQUAL *cond_equal)
{
  if (item->type() == Item::FUNC_ITEM &&
         ((Item_func*) item)->functype() == Item_func::EQ_FUNC)
  {
    Item *left_item= ((Item_func*) item)->arguments()[0];
    Item *right_item= ((Item_func*) item)->arguments()[1];
    if (left_item->type() == Item::FIELD_ITEM &&
        right_item->type() == Item::FIELD_ITEM)
    {
      /* The predicate the form field1=field2 is processed */

      Field *left_field= ((Item_field*) left_item)->field;
      Field *right_field= ((Item_field*) right_item)->field;

      if (!left_field->eq_def(right_field))
        return FALSE;

unknown's avatar
unknown committed
6404
      if (left_field->eq(right_field))  /* f = f */
6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417
        return TRUE;
      
      /* Search for multiple equalities containing field1 and/or field2 */
      bool left_copyfl, right_copyfl;
      Item_equal *left_item_equal=
                 find_item_equal(cond_equal, left_field, &left_copyfl);
      Item_equal *right_item_equal= 
                 find_item_equal(cond_equal, right_field, &right_copyfl);

      if (left_item_equal && left_item_equal == right_item_equal)
      {
        /* 
           The equality predicate is inference of one of the existing
unknown's avatar
unknown committed
6418 6419
           multiple equalities, i.e the condition is already covered
           by upper level equalities
6420 6421 6422 6423 6424 6425 6426
        */
          return TRUE;
      }
      
      /* Copy the found multiple equalities at the current level if needed */
      if (left_copyfl)
      {
unknown's avatar
unknown committed
6427
        /* left_item_equal of an upper level contains left_item */
6428 6429 6430 6431 6432
        left_item_equal= new Item_equal(left_item_equal);
        cond_equal->current_level.push_back(left_item_equal);
      }
      if (right_copyfl)
      {
unknown's avatar
unknown committed
6433
        /* right_item_equal of an upper level contains right_item */
6434 6435 6436 6437 6438 6439
        right_item_equal= new Item_equal(right_item_equal);
        cond_equal->current_level.push_back(right_item_equal);
      }

      if (left_item_equal)
      { 
unknown's avatar
unknown committed
6440
        /* left item was found in the current or one of the upper levels */
6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454
        if (! right_item_equal)
          left_item_equal->add((Item_field *) right_item);
        else
        {
          /* Merge two multiple equalities forming a new one */
          left_item_equal->merge(right_item_equal);
          /* Remove the merged multiple equality from the list */
          List_iterator<Item_equal> li(cond_equal->current_level);
          while ((li++) != right_item_equal);
          li.remove();
        }
      }
      else
      { 
unknown's avatar
unknown committed
6455
        /* left item was not found neither the current nor in upper levels  */
6456 6457 6458 6459
         if (right_item_equal)
           right_item_equal->add((Item_field *) left_item);
         else 
         {
unknown's avatar
unknown committed
6460
           /* None of the fields was found in multiple equalities */
6461 6462 6463 6464 6465 6466 6467
           Item_equal *item= new Item_equal((Item_field *) left_item,
                                            (Item_field *) right_item);
           cond_equal->current_level.push_back(item);
         }
      }
      return TRUE;
    }
unknown's avatar
unknown committed
6468

6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488
    {
      /* The predicate of the form field=const/const=field is processed */
      Item *const_item= 0;
      Item_field *field_item= 0;
      if (left_item->type() == Item::FIELD_ITEM && 
          right_item->const_item())
      {
        field_item= (Item_field*) left_item;
        const_item= right_item;
      }
      else if (right_item->type() == Item::FIELD_ITEM && 
               left_item->const_item())
      {
        field_item= (Item_field*) right_item;
        const_item= left_item;
      }
      if (const_item &&
          field_item->result_type() == const_item->result_type())
      {
        bool copyfl;
unknown's avatar
unknown committed
6489 6490

        if (field_item->result_type() == STRING_RESULT &&
unknown's avatar
unknown committed
6491
              ((Field_str *) field_item->field)->charset() !=
unknown's avatar
unknown committed
6492 6493 6494
               ((Item_cond *) item)->compare_collation())
          return FALSE;

6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526
        Item_equal *item_equal = find_item_equal(cond_equal,
                                                 field_item->field, &copyfl);
        if (copyfl)
        {
          item_equal= new Item_equal(item_equal);
          cond_equal->current_level.push_back(item_equal);
        }
        if (item_equal)
        {
          /* 
            The flag cond_false will be set to 1 after this, if item_equal
            already contains a constant and its value is  not equal to
            the value of const_item.
          */
          item_equal->add(const_item);
        }
        else
        {
          item_equal= new Item_equal(const_item, field_item);
          cond_equal->current_level.push_back(item_equal);
        }
        return TRUE;
      }
    }
  }
  return FALSE;
}

/* 
  Replace all equality predicates in a condition by multiple equality items

  SYNOPSIS
unknown's avatar
unknown committed
6527
    build_equal_items_for_cond()
6528 6529 6530 6531 6532 6533 6534 6535 6536
    cond       condition(expression) where to make replacement
    inherited  path to all inherited multiple equality items

  DESCRIPTION
    At each 'and' level the function detects items for equality predicates
    and replaced them by a set of multiple equality items of class Item_equal,
    taking into account inherited equalities from upper levels. 
    If an equality predicate is used not in a conjunction it's just
    replaced by a multiple equality predicate.
unknown's avatar
unknown committed
6537 6538 6539 6540 6541
    For each 'and' level the function set a pointer to the inherited
    multiple equalities in the cond_equal field of the associated
    object of the type Item_cond_and.   
    The function also traverses the cond tree and and for each field reference
    sets a pointer to the multiple equality item containing the field, if there
6542
    is any. If this multiple equality equates fields to a constant the
unknown's avatar
unknown committed
6543 6544 6545 6546 6547
    function replace the field reference by the constant.
    The function also determines the maximum number of members in 
    equality lists of each Item_cond_and object assigning it to
    cond_equal->max_members of this object and updating accordingly
    the upper levels COND_EQUAL structures.  
6548 6549 6550 6551 6552 6553 6554

  NOTES
    Multiple equality predicate =(f1,..fn) is equivalent to the conjuction of
    f1=f2, .., fn-1=fn. It substitutes any inference from these
    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)).
unknown's avatar
unknown committed
6555
    The function always makes a substitution of all equality predicates occured
6556 6557 6558 6559 6560 6561
    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.
    E.g. (t1.a=t2.b AND t2.b>5 AND t1.a=t3.c) is replaced by 
    (=(t1.a,t2.b,t3.c) AND t2.b>5), not by
    (=(t1.a,t2.b) AND =(t1.a,t3.c) AND t2.b>5);
unknown's avatar
unknown committed
6562
    while (t1.a=t2.b AND t2.b>5 AND t3.c=t4.d) is replaced by
6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575
    (=(t1.a,t2.b) AND =(t3.c=t4.d) AND t2.b>5),
    but if additionally =(t4.d,t2.b) is inherited, it
    will be replaced by (=(t1.a,t2.b,t3.c,t4.d) AND t2.b>5)

  IMPLEMENTATION
    The function performs the substitution in a recursive descent by
    the condtion tree, passing to the next AND level a chain of multiple
    equality predicates which have been built at the upper levels.
    The Item_equal items built at the level are attached to other 
    non-equality conjucts as a sublist. The pointer to the inherited
    multiple equalities is saved in the and condition object (Item_cond_and).
    This chain allows us for any field reference occurence easyly to find a 
    multiple equality that must be held for this occurence.
unknown's avatar
unknown committed
6576 6577 6578 6579 6580 6581 6582
    For each AND level we do the following:
    - scan it for all equality predicate (=) items
    - join them into disjoint Item_equal() groups
    - process the included OR conditions recursively to do the same for 
      lower AND levels. 
    We need to do things in this order as lower AND levels need to know about
    all possible Item_equal objects in upper levels.
6583 6584 6585 6586 6587

  RETURN
    pointer to the transformed condition
*/

unknown's avatar
unknown committed
6588
static COND *build_equal_items_for_cond(COND *cond,
6589 6590
                                        COND_EQUAL *inherited)
{
unknown's avatar
unknown committed
6591 6592
  Item_equal *item_equal;
  uint members;
6593
  COND_EQUAL cond_equal;
unknown's avatar
unknown committed
6594
  cond_equal.upper_levels= inherited;
6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609

  if (cond->type() == Item::COND_ITEM)
  {
    bool and_level= ((Item_cond*) cond)->functype() ==
      Item_func::COND_AND_FUNC;
    List<Item> *args= ((Item_cond*) cond)->argument_list();
    
    List_iterator<Item> li(*args);
    Item *item;

    if (and_level)
    {
      /*
         Retrieve all conjucts of this level detecting the equality
         that are subject to substitution by multiple equality items and
unknown's avatar
unknown committed
6610
         removing each such predicate from the conjunction after having 
6611 6612 6613 6614
         found/created a multiple equality whose inference the predicate is.
     */      
      while ((item= li++))
      {
6615 6616 6617 6618 6619
        /*
          PS/SP note: we can safely remove a node from AND-OR
          structure here because it's restored before each
          re-execution of any prepared statement/stored procedure.
        */
6620 6621 6622 6623 6624
        if (check_equality(item, &cond_equal))
          li.remove();
      }

      List_iterator_fast<Item_equal> it(cond_equal.current_level);
unknown's avatar
unknown committed
6625
      while ((item_equal= it++))
6626
      {
unknown's avatar
unknown committed
6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643
        item_equal->fix_length_and_dec();
        item_equal->update_used_tables();
        members= item_equal->members();
        if (cond_equal.max_members < members)
          cond_equal.max_members= members; 
      }
      members= cond_equal.max_members;
      if (inherited && inherited->max_members < members)
      {
        do
        {
	  inherited->max_members= members;
          inherited= inherited->upper_levels;
        }
        while (inherited);
      }

6644 6645 6646 6647 6648 6649 6650
      ((Item_cond_and*)cond)->cond_equal= cond_equal;
      inherited= &(((Item_cond_and*)cond)->cond_equal);
    }
    /*
       Make replacement of equality predicates for lower levels
       of the condition expression.
    */
unknown's avatar
unknown committed
6651 6652
    li.rewind();
    while((item= li++))
6653 6654
    { 
      Item *new_item;
unknown's avatar
unknown committed
6655
      if ((new_item = build_equal_items_for_cond(item, inherited))!= item)
6656 6657
      {
        /* This replacement happens only for standalone equalities */
6658 6659 6660 6661 6662
        /*
          This is ok with PS/SP as the replacement is done for
          arguments of an AND/OR item, which are restored for each
          execution of PS/SP.
        */
unknown's avatar
unknown committed
6663
        li.replace(new_item);
6664 6665 6666 6667 6668 6669 6670
      }
    }
    if (and_level)
      args->concat((List<Item> *)&cond_equal.current_level);
  }
  else if (cond->type() == Item::FUNC_ITEM)
  {
unknown's avatar
unknown committed
6671 6672 6673 6674 6675 6676 6677 6678 6679 6680
    /*
      If an equality predicate forms the whole and level,
      we call it standalone equality and it's processed here.
      E.g. in the following where condition
      WHERE a=5 AND (b=5 or a=c)
      (b=5) and (a=c) are standalone equalities.
      In general we can't leave alone standalone eqalities:
      for WHERE a=b AND c=d AND (b=c OR d=5)
      b=c is replaced by =(a,b,c,d).  
     */
6681 6682 6683
    if (check_equality(cond, &cond_equal) &&
        (item_equal= cond_equal.current_level.pop()))
    {
unknown's avatar
unknown committed
6684 6685
      item_equal->fix_length_and_dec();
      item_equal->update_used_tables();
6686 6687
      return item_equal;
    }
unknown's avatar
unknown committed
6688 6689 6690 6691 6692 6693 6694
    /* 
      For each field reference in cond, not from equalitym predicates,
      set a pointer to the multiple equality if belongs to (if there is any)
    */ 
    cond= cond->transform(&Item::equal_fields_propagator,
                            (byte *) inherited);
    cond->update_used_tables();
6695
  }
unknown's avatar
unknown committed
6696 6697 6698
  return cond;
}

unknown's avatar
unknown committed
6699

unknown's avatar
unknown committed
6700 6701 6702 6703 6704 6705
/* 
  Build multiple equalities for a condition and all on expressions that
  inherit these multiple equalities

  SYNOPSIS
    build_equal_items()
unknown's avatar
unknown committed
6706
    thd			Thread handler
unknown's avatar
unknown committed
6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757
    cond                condition to build the multiple equalities for
    inherited           path to all inherited multiple equality items
    join_list           list of join tables to which the condition refers to
    cond_equal_ref :out pointer to the structure to place built equalities in

  DESCRIPTION
    The function first applies the build_equal_items_for_cond function
    to build all multiple equalities for condition cond utilizing equalities
    referred through the parameter inherited. The extended set of
    equalities is returned in the structure referred by the cond_equal_ref
    parameter. After this the function calls itself recursively for
    all on expressions whose direct references can be found in join_list
    and who inherit directly the multiple equalities just having built.

  NOTES
    The on expression used in an outer join operation inherits all equalities
    from the on expression of the embedding join, if there is any, or 
    otherwise - from the where condition.
    This fact is not obvious, but presumably can be proved.
    Consider the following query:
      SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t1.a=t3.a AND t2.a=t4.a
        WHERE t1.a=t2.a;
    If the on expression in the query inherits =(t1.a,t2.a), then we
    can build the multiple equality =(t1.a,t2.a,t3.a,t4.a) that infers
    the equality t3.a=t4.a. Although the on expression
    t1.a=t3.a AND t2.a=t4.a AND t3.a=t4.a is not equivalent to the one
    in the query the latter can be replaced by the former: the new query
    will return the same result set as the original one.

    Interesting that multiple equality =(t1.a,t2.a,t3.a,t4.a) allows us
    to use t1.a=t3.a AND t3.a=t4.a under the on condition:
      SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t1.a=t3.a AND t3.a=t4.a
        WHERE t1.a=t2.a
    This query equivalent to:
      SELECT * FROM (t1 LEFT JOIN (t3,t4) ON t1.a=t3.a AND t3.a=t4.a),t2
        WHERE t1.a=t2.a
    Similarly the original query can be rewritten to the query:
      SELECT * FROM (t1,t2) LEFT JOIN (t3,t4) ON t2.a=t4.a AND t3.a=t4.a
        WHERE t1.a=t2.a
    that is equivalent to:   
      SELECT * FROM (t2 LEFT JOIN (t3,t4)ON t2.a=t4.a AND t3.a=t4.a), t1
        WHERE t1.a=t2.a
    Thus, applying equalities from the where condition we basically
    can get more freedom in performing join operations.
    Althogh we don't use this property now, it probably makes sense to use 
    it in the future.    
         
  RETURN
    pointer to the transformed condition containing multiple equalities
*/
   
unknown's avatar
unknown committed
6758
static COND *build_equal_items(THD *thd, COND *cond,
unknown's avatar
unknown committed
6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796
                               COND_EQUAL *inherited,
                               List<TABLE_LIST> *join_list,
                               COND_EQUAL **cond_equal_ref)
{
  COND_EQUAL *cond_equal= 0;

  if (cond) 
  {
    cond= build_equal_items_for_cond(cond, inherited);
    cond->update_used_tables();
    if (cond->type() == Item::COND_ITEM &&
        ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
      cond_equal= &((Item_cond_and*) cond)->cond_equal;
    else if (cond->type() == Item::FUNC_ITEM &&
             ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
    {
      cond_equal= new COND_EQUAL;
      cond_equal->current_level.push_back((Item_equal *) cond);
    }
  }
  if (cond_equal)
  {
    cond_equal->upper_levels= inherited;
    inherited= cond_equal;
  }
  *cond_equal_ref= cond_equal;

  if (join_list)
  {
    TABLE_LIST *table;
    List_iterator<TABLE_LIST> li(*join_list);

    while ((table= li++))
    {
      if (table->on_expr)
      {
        List<TABLE_LIST> *join_list= table->nested_join ?
	                             &table->nested_join->join_list : NULL;
6797 6798 6799 6800 6801 6802
        /*
          We can modify table->on_expr because its old value will
          be restored before re-execution of PS/SP.
        */
        table->on_expr= build_equal_items(thd, table->on_expr, inherited,
                                          join_list, &table->cond_equal);
unknown's avatar
unknown committed
6803 6804 6805 6806
      }
    }
  }

6807 6808 6809
  return cond;
}    

unknown's avatar
unknown committed
6810

unknown's avatar
unknown committed
6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854
/* 
  Compare field items by table order in the execution plan
 
  SYNOPSIS
    compare_fields_by_table_order()
    field1          first field item to compare
    field2          second field item to compare
    table_join_idx  index to tables determining table order    

  DESCRIPTION
    field1 considered as better than field2 if the table containing
    field1 is accessed earlier than the table containing field2.   
    The function finds out what of two fields is better according
    this criteria.

  RETURN
     1, if field1 is better than field2 
    -1, if field2 is better than field1
     0, otherwise
*/

static int compare_fields_by_table_order(Item_field *field1,
                                  Item_field *field2,
                                  void *table_join_idx)
{
  int cmp= 0;
  bool outer_ref= 0;
  if (field2->used_tables() & OUTER_REF_TABLE_BIT)
  {  
    outer_ref= 1;
    cmp= -1;
  }
  if (field2->used_tables() & OUTER_REF_TABLE_BIT)
  {
    outer_ref= 1;
    cmp++;
  }
  if (outer_ref)
    return cmp;
  JOIN_TAB **idx= (JOIN_TAB **) table_join_idx;
  cmp= idx[field2->field->table->tablenr]-idx[field1->field->table->tablenr];
  return cmp < 0 ? -1 : (cmp ? 1 : 0);
}

6855 6856 6857 6858 6859 6860 6861

/* 
  Generate minimal set of simple equalities equivalent to a multiple equality
 
  SYNOPSIS
    eliminate_item_equal()
    cond            condition to add the generated equality to
unknown's avatar
unknown committed
6862
    upper_levels    structure to access multiple equality of upper levels
6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875
    item_equal      multiple equality to generate simple equality from     

  DESCRIPTION
    The function retrieves the fields of the multiple equality item
    item_equal and  for each field f:
    - if item_equal contains const it generates the equality f=const_item;
    - otherwise, if f is not the first field, generates the equality
      f=item_equal->get_first().
    All generated equality are added to the cond conjunction.

  NOTES
    Before generating an equality function checks that it has not
    been generated for multiple equalies of the upper levels.
unknown's avatar
unknown committed
6876 6877 6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889
    E.g. for the following where condition
    WHERE a=5 AND ((a=b AND b=c) OR  c>4)
    the upper level AND condition will contain =(5,a),
    while the lower level AND condition will contain =(5,a,b,c).
    When splitting =(5,a,b,c) into a separate equality predicates
    we should omit 5=a, as we have it already in the upper level.
    The following where condition gives us a more complicated case:
    WHERE t1.a=t2.b AND t3.c=t4.d AND (t2.b=t3.c OR t4.e>5 ...) AND ...
    Given the tables are accessed in the order t1->t2->t3->t4 for
    the selected query execution plan the lower level multiple
    equality =(t1.a,t2.b,t3.c,t4.d) formally  should be converted to
    t1.a=t2.b AND t1.a=t3.c AND t1.a=t4.d. But t1.a=t2.a will be
    generated for the upper level. Also t3.c=t4.d will be generated there.
    So only t1.a=t3.c should be left in the lower level.
6890 6891 6892 6893 6894
    If cond is equal to 0, then not more then one equality is generated
    and a pointer to it is returned as the result of the function.

  RETURN
    The condition with generated simple equalities or
unknown's avatar
unknown committed
6895 6896
    a pointer to the simple generated equality, if success.
    0, otherwise.
6897 6898
*/

unknown's avatar
unknown committed
6899
static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
6900 6901
                                  Item_equal *item_equal)
{
unknown's avatar
unknown committed
6902 6903
  List<Item> eq_list;
  Item_func_eq *eq_item= 0;
unknown's avatar
unknown committed
6904
  if (((Item *) item_equal)->const_item() && !item_equal->val_int())
unknown's avatar
unknown committed
6905
    return new Item_int((longlong) 0,1); 
6906 6907
  Item *item_const= item_equal->get_const();
  Item_equal_iterator it(*item_equal);
unknown's avatar
unknown committed
6908
  Item *head;
6909 6910 6911 6912 6913 6914 6915 6916 6917 6918
  if (item_const)
    head= item_const;
  else
  {
    head= item_equal->get_first();
    it++;
  }
  Item_field *item_field;
  while ((item_field= it++))
  {
unknown's avatar
unknown committed
6919
    Item_equal *upper= item_field->find_item_equal(upper_levels);
6920 6921 6922
    Item_field *item= item_field;
    if (upper)
    { 
unknown's avatar
unknown committed
6923 6924
      if (item_const && upper->get_const())
        item= 0;
6925 6926 6927 6928 6929
      else
      {
        Item_equal_iterator li(*item_equal);
        while ((item= li++) != item_field)
        {
unknown's avatar
unknown committed
6930
          if (item->find_item_equal(upper_levels) == upper)
6931 6932 6933 6934 6935 6936
            break;
        }
      }
    }
    if (item == item_field)
    {
unknown's avatar
unknown committed
6937 6938 6939 6940 6941 6942
      if (eq_item)
        eq_list.push_back(eq_item);
      eq_item= new Item_func_eq(item_field, head);
      if (!eq_item)
        return 0;
      eq_item->set_cmp_func();
unknown's avatar
unknown committed
6943
      eq_item->quick_fix_field();
unknown's avatar
unknown committed
6944
   }
6945
  }
unknown's avatar
unknown committed
6946 6947

  if (!cond && !eq_list.head())
unknown's avatar
unknown committed
6948 6949 6950
  {
    if (!eq_item)
      return new Item_int((longlong) 1,1);
unknown's avatar
unknown committed
6951
    return eq_item;
unknown's avatar
unknown committed
6952
  }
unknown's avatar
unknown committed
6953

unknown's avatar
unknown committed
6954 6955
  if (eq_item)
    eq_list.push_back(eq_item);
6956
  if (!cond)
unknown's avatar
unknown committed
6957 6958 6959
    cond= new Item_cond_and(eq_list);
  else
    ((Item_cond *) cond)->add_at_head(&eq_list);
unknown's avatar
unknown committed
6960 6961 6962

  cond->quick_fix_field();
  cond->update_used_tables();
unknown's avatar
unknown committed
6963
   
6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974
  return cond;
}


/* 
  Substitute every field reference in a condition by the best equal field 
  and eliminate all multiplle equality predicates
 
  SYNOPSIS
    substitute_for_best_equal_field()
    cond            condition to process
unknown's avatar
unknown committed
6975
    cond_equal      multiple equalities to take into consideration
6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987 6988 6989 6990 6991 6992 6993 6994 6995 6996 6997 6998 6999 7000
    table_join_idx  index to tables determining field preference

  DESCRIPTION
    The function retrieves the cond condition and for each encountered
    multiple equality predicate it sorts the field references in it
    according to the order of tables specified by the table_join_idx
    parameter. Then it eliminates the multiple equality predicate it
    replacing it by the conjunction of simple equality predicates 
    equating every field from the multiple equality to the first
    field in it, or to the constant, if there is any.
    After this the function retrieves all other conjuncted
    predicates substitute every field reference by the field reference
    to the first equal field or equal constant if there are any.
 
  NOTES
    At the first glance full sort of fields in multiple equality
    seems to be an overkill. Yet it's not the case due to possible
    new fields in multiple equality item of lower levels. We want
    the order in them to comply with the order of upper levels.

  RETURN
    The transformed condition
*/

static COND* substitute_for_best_equal_field(COND *cond,
unknown's avatar
unknown committed
7001
                                             COND_EQUAL *cond_equal,
7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017
                                             void *table_join_idx)
{
  Item_equal *item_equal;

  if (cond->type() == Item::COND_ITEM)
  {
    List<Item> *cond_list= ((Item_cond*) cond)->argument_list();

    bool and_level= ((Item_cond*) cond)->functype() ==
                      Item_func::COND_AND_FUNC;
    if (and_level)
    {
      cond_equal= &((Item_cond_and *) cond)->cond_equal;
      cond_list->disjoin((List<Item> *) &cond_equal->current_level);

      List_iterator_fast<Item_equal> it(cond_equal->current_level);      
unknown's avatar
unknown committed
7018
      while ((item_equal= it++))
7019
      {
unknown's avatar
unknown committed
7020
        item_equal->sort(&compare_fields_by_table_order, table_join_idx);
7021 7022 7023 7024 7025 7026 7027
      }
    }
    
    List_iterator<Item> li(*cond_list);
    Item *item;
    while ((item= li++))
    {
unknown's avatar
unknown committed
7028
      Item *new_item =substitute_for_best_equal_field(item, cond_equal,
7029 7030 7031 7032 7033
                                                      table_join_idx);
      /*
        This works OK with PS/SP re-execution as changes are made to
        the arguments of AND/OR items only
      */
7034 7035
      if (new_item != item)
        li.replace(new_item);
7036
    }
7037 7038 7039 7040

    if (and_level)
    {
      List_iterator_fast<Item_equal> it(cond_equal->current_level);
unknown's avatar
unknown committed
7041
      while ((item_equal= it++))
7042
      {
unknown's avatar
unknown committed
7043
        eliminate_item_equal(cond, cond_equal->upper_levels, item_equal);
7044 7045 7046 7047 7048 7049 7050
      }
    }
  }
  else if (cond->type() == Item::FUNC_ITEM && 
           ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
  {
    item_equal= (Item_equal *) cond;
unknown's avatar
unknown committed
7051
    item_equal->sort(&compare_fields_by_table_order, table_join_idx);
unknown's avatar
unknown committed
7052 7053 7054
    if (cond_equal && cond_equal->current_level.head() == item_equal)
      cond_equal= 0;
    return eliminate_item_equal(0, cond_equal, item_equal);
7055 7056
  }
  else
unknown's avatar
unknown committed
7057
    cond->transform(&Item::replace_equal_field, 0);
7058 7059 7060
  return cond;
}

unknown's avatar
unknown committed
7061

unknown's avatar
unknown committed
7062
/*
7063 7064
  change field = field to field = const for each found field = const in the
  and_level
unknown's avatar
unknown committed
7065 7066 7067
*/

static void
7068 7069 7070
change_cond_ref_to_const(THD *thd, I_List<COND_CMP> *save_list,
                         Item *and_father, Item *cond,
                         Item *field, Item *value)
unknown's avatar
unknown committed
7071 7072 7073 7074 7075 7076 7077 7078
{
  if (cond->type() == Item::COND_ITEM)
  {
    bool and_level= ((Item_cond*) cond)->functype() ==
      Item_func::COND_AND_FUNC;
    List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
    Item *item;
    while ((item=li++))
7079
      change_cond_ref_to_const(thd, save_list,and_level ? cond : item, item,
unknown's avatar
unknown committed
7080 7081 7082 7083 7084 7085 7086
			       field, value);
    return;
  }
  if (cond->eq_cmp_result() == Item::COND_OK)
    return;					// Not a boolean function

  Item_bool_func2 *func=  (Item_bool_func2*) cond;
7087 7088 7089
  Item **args= func->arguments();
  Item *left_item=  args[0];
  Item *right_item= args[1];
unknown's avatar
unknown committed
7090 7091
  Item_func::Functype functype=  func->functype();

7092 7093 7094 7095
  if (right_item->eq(field,0) && left_item != value &&
      (left_item->result_type() != STRING_RESULT ||
       value->result_type() != STRING_RESULT ||
       left_item->collation.collation == value->collation.collation))
unknown's avatar
unknown committed
7096 7097 7098 7099
  {
    Item *tmp=value->new_item();
    if (tmp)
    {
7100
      thd->change_item_tree(args + 1, tmp);
unknown's avatar
unknown committed
7101 7102 7103 7104 7105 7106 7107 7108 7109
      func->update_used_tables();
      if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC)
	  && and_father != cond && !left_item->const_item())
      {
	cond->marker=1;
	COND_CMP *tmp2;
	if ((tmp2=new COND_CMP(and_father,func)))
	  save_list->push_back(tmp2);
      }
7110
      func->set_cmp_func();
unknown's avatar
unknown committed
7111 7112
    }
  }
7113 7114 7115 7116
  else if (left_item->eq(field,0) && right_item != value &&
           (right_item->result_type() != STRING_RESULT ||
            value->result_type() != STRING_RESULT ||
            right_item->collation.collation == value->collation.collation))
unknown's avatar
unknown committed
7117 7118 7119 7120
  {
    Item *tmp=value->new_item();
    if (tmp)
    {
7121 7122
      thd->change_item_tree(args, tmp);
      value= tmp;
unknown's avatar
unknown committed
7123 7124 7125 7126
      func->update_used_tables();
      if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC)
	  && and_father != cond && !right_item->const_item())
      {
7127
        args[0]= args[1];                       // For easy check
7128
        thd->change_item_tree(args + 1, value);
unknown's avatar
unknown committed
7129 7130 7131 7132 7133
	cond->marker=1;
	COND_CMP *tmp2;
	if ((tmp2=new COND_CMP(and_father,func)))
	  save_list->push_back(tmp2);
      }
7134
      func->set_cmp_func();
unknown's avatar
unknown committed
7135 7136 7137 7138
    }
  }
}

7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171
/*
  Remove additional condition inserted by IN/ALL/ANY transformation

  SYNOPSIS
    remove_additional_cond()
    conds - condition for processing

  RETURN VALUES
    new conditions
*/

static Item *remove_additional_cond(Item* conds)
{
  if (conds->name == in_additional_cond)
    return 0;
  if (conds->type() == Item::COND_ITEM)
  {
    Item_cond *cnd= (Item_cond*) conds;
    List_iterator<Item> li(*(cnd->argument_list()));
    Item *item;
    while ((item= li++))
    {
      if (item->name == in_additional_cond)
      {
	li.remove();
	if (cnd->argument_list()->elements == 1)
	  return cnd->argument_list()->head();
	return conds;
      }
    }
  }
  return conds;
}
unknown's avatar
unknown committed
7172 7173

static void
7174 7175
propagate_cond_constants(THD *thd, I_List<COND_CMP> *save_list,
                         COND *and_father, COND *cond)
unknown's avatar
unknown committed
7176 7177 7178 7179 7180
{
  if (cond->type() == Item::COND_ITEM)
  {
    bool and_level= ((Item_cond*) cond)->functype() ==
      Item_func::COND_AND_FUNC;
unknown's avatar
unknown committed
7181
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
7182 7183 7184 7185
    Item *item;
    I_List<COND_CMP> save;
    while ((item=li++))
    {
7186
      propagate_cond_constants(thd, &save,and_level ? cond : item, item);
unknown's avatar
unknown committed
7187 7188 7189 7190 7191 7192
    }
    if (and_level)
    {						// Handle other found items
      I_List_iterator<COND_CMP> cond_itr(save);
      COND_CMP *cond_cmp;
      while ((cond_cmp=cond_itr++))
7193 7194 7195 7196 7197 7198
      {
        Item **args= cond_cmp->cmp_func->arguments();
        if (!args[0]->const_item())
          change_cond_ref_to_const(thd, &save,cond_cmp->and_level,
                                   cond_cmp->and_level, args[0], args[1]);
      }
unknown's avatar
unknown committed
7199 7200
    }
  }
7201
  else if (and_father != cond && !cond->marker)		// In a AND group
unknown's avatar
unknown committed
7202 7203 7204 7205 7206 7207
  {
    if (cond->type() == Item::FUNC_ITEM &&
	(((Item_func*) cond)->functype() == Item_func::EQ_FUNC ||
	 ((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC))
    {
      Item_func_eq *func=(Item_func_eq*) cond;
7208 7209 7210
      Item **args= func->arguments();
      bool left_const= args[0]->const_item();
      bool right_const= args[1]->const_item();
7211
      if (!(left_const && right_const) &&
7212
          args[0]->result_type() == args[1]->result_type())
unknown's avatar
unknown committed
7213 7214 7215
      {
	if (right_const)
	{
7216
          resolve_const_item(thd, &args[1], args[0]);
unknown's avatar
unknown committed
7217
	  func->update_used_tables();
7218 7219
          change_cond_ref_to_const(thd, save_list, and_father, and_father,
                                   args[0], args[1]);
unknown's avatar
unknown committed
7220 7221 7222
	}
	else if (left_const)
	{
7223
          resolve_const_item(thd, &args[0], args[1]);
unknown's avatar
unknown committed
7224
	  func->update_used_tables();
7225 7226
          change_cond_ref_to_const(thd, save_list, and_father, and_father,
                                   args[1], args[0]);
unknown's avatar
unknown committed
7227 7228 7229 7230 7231 7232 7233
	}
      }
    }
  }
}


7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297
/*
  Simplify joins replacing outer joins by inner joins whenever it's possible

  SYNOPSIS
    simplify_joins()
    join        reference to the query info
    join_list   list representation of the join to be converted
    conds       conditions to add on expressions for converted joins
    top         true <=> conds is the where condition  

  DESCRIPTION
    The function, during a retrieval of join_list,  eliminates those
    outer joins that can be converted into inner join, possibly nested.
    It also moves the on expressions for the converted outer joins
    and from inner joins to conds.
    The function also calculates some attributes for nested joins:
    - used_tables    
    - not_null_tables
    - dep_tables.
    - on_expr_dep_tables
    The first two attributes are used to test whether an outer join can
    be substituted for an inner join. The third attribute represents the
    relation 'to be dependent on' for tables. If table t2 is dependent
    on table t1, then in any evaluated execution plan table access to
    table t2 must precede access to table t2. This relation is used also
    to check whether the query contains  invalid cross-references.
    The forth attribute is an auxiliary one and is used to calculate
    dep_tables.
    As the attribute dep_tables qualifies possibles orders of tables in the
    execution plan, the dependencies required by the straight join
    modifiers are reflected in this attribute as well.
    The function also removes all braces that can be removed from the join
    expression without changing its meaning.

  NOTES
    An outer join can be replaced by an inner join if the where condition
    or the on expression for an embedding nested join contains a conjunctive
    predicate rejecting null values for some attribute of the inner tables.

    E.g. in the query:    
      SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a WHERE t2.b < 5
    the predicate t2.b < 5 rejects nulls.
    The query is converted first to:
      SELECT * FROM t1 INNER JOIN t2 ON t2.a=t1.a WHERE t2.b < 5
    then to the equivalent form:
      SELECT * FROM t1, t2 ON t2.a=t1.a WHERE t2.b < 5 AND t2.a=t1.a.

    Similarly the following query:
      SELECT * from t1 LEFT JOIN (t2, t3) ON t2.a=t1.a t3.b=t1.b
        WHERE t2.c < 5  
    is converted to:
      SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a t3.b=t1.b 

    One conversion might trigger another:
      SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a
                       LEFT JOIN t3 ON t3.b=t2.b
        WHERE t3 IS NOT NULL =>
      SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t1.a, t3
        WHERE t3 IS NOT NULL AND t3.b=t2.b => 
      SELECT * FROM t1, t2, t3
        WHERE t3 IS NOT NULL AND t3.b=t2.b AND t2.a=t1.a
   
    The function removes all unnecessary braces from the expression
    produced by the conversions.
7298
    E.g. SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b
7299
    finally is converted to: 
7300
      SELECT * FROM t1, t2, t3 WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b
7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334

    It also will remove braces from the following queries:
      SELECT * from (t1 LEFT JOIN t2 ON t2.a=t1.a) LEFT JOIN t3 ON t3.b=t2.b
      SELECT * from (t1, (t2,t3)) WHERE t1.a=t2.a AND t2.b=t3.b.

    The benefit of this simplification procedure is that it might return 
    a query for which the optimizer can evaluate execution plan with more
    join orders. With a left join operation the optimizer does not
    consider any plan where one of the inner tables is before some of outer
    tables.

  IMPLEMENTATION.
    The function is implemented by a recursive procedure.  On the recursive
    ascent all attributes are calculated, all outer joins that can be
    converted are replaced and then all unnecessary braces are removed.
    As join list contains join tables in the reverse order sequential
    elimination of outer joins does not requite extra recursive calls.

  EXAMPLES
    Here is an example of a join query with invalid cross references:
      SELECT * FROM t1 LEFT JOIN t2 ON t2.a=t3.a LEFT JOIN ON  t3.b=t1.b 
     
  RETURN VALUE
    The new condition, if success
    0, otherwise  
*/

static COND *
simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
{
  TABLE_LIST *table;
  NESTED_JOIN *nested_join;
  TABLE_LIST *prev_table= 0;
  List_iterator<TABLE_LIST> li(*join_list);
7335
  DBUG_ENTER("simplify_joins");
7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353

  /* 
    Try to simplify join operations from join_list.
    The most outer join operation is checked for conversion first. 
  */
  while ((table= li++))
  {
    table_map used_tables;
    table_map not_null_tables= (table_map) 0;

    if ((nested_join= table->nested_join))
    {
      /* 
         If the element of join_list is a nested join apply
         the procedure to its nested join list first.
      */
      if (table->on_expr)
      {
unknown's avatar
unknown committed
7354
        Item *expr;
7355 7356 7357 7358 7359 7360 7361 7362
        /* 
           If an on expression E is attached to the table, 
           check all null rejected predicates in this expression.
           If such a predicate over an attribute belonging to
           an inner table of an embedded outer join is found,
           the outer join is converted to an inner join and
           the corresponding on expression is added to E. 
	*/ 
unknown's avatar
unknown committed
7363 7364
        expr= simplify_joins(join, &nested_join->join_list,
                             table->on_expr, FALSE);
7365
        table->prep_on_expr= table->on_expr= expr;
7366 7367 7368 7369 7370 7371 7372 7373 7374 7375 7376 7377 7378 7379 7380 7381 7382 7383 7384
      }
      nested_join->used_tables= (table_map) 0;
      nested_join->not_null_tables=(table_map) 0;
      conds= simplify_joins(join, &nested_join->join_list, conds, top);
      used_tables= nested_join->used_tables;
      not_null_tables= nested_join->not_null_tables;  
    }
    else
    {
      used_tables= table->table->map;
      if (conds)
        not_null_tables= conds->not_null_tables();
    }
      
    if (table->embedding)
    {
      table->embedding->nested_join->used_tables|= used_tables;
      table->embedding->nested_join->not_null_tables|= not_null_tables;
    }
7385 7386

    if (!table->outer_join || (used_tables & not_null_tables))
7387 7388 7389 7390 7391 7392 7393 7394 7395 7396 7397 7398
    {
      /* 
        For some of the inner tables there are conjunctive predicates
        that reject nulls => the outer join can be replaced by an inner join.
      */
      table->outer_join= 0;
      if (table->on_expr)
      {
        /* Add on expression to the where condition. */
        if (conds)
        {
          conds= and_conds(conds, table->on_expr);
7399
          conds->top_level_item();
7400 7401 7402
          /* conds is always a new item as both cond and on_expr existed */
          DBUG_ASSERT(!conds->fixed);
          conds->fix_fields(join->thd, 0, &conds);
7403 7404 7405
        }
        else
          conds= table->on_expr; 
7406
        table->prep_on_expr= table->on_expr= 0;
7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438
      }
    }
    
    if (!top)
      continue;

    /* 
      Only inner tables of non-convertible outer joins
      remain with on_expr.
    */ 
    if (table->on_expr)
    {
      table->dep_tables|= table->on_expr->used_tables(); 
      if (table->embedding)
      {
        table->dep_tables&= ~table->embedding->nested_join->used_tables;   
        /*
           Embedding table depends on tables used
           in embedded on expressions. 
        */
        table->embedding->on_expr_dep_tables|= table->on_expr->used_tables();
      }
      else
        table->dep_tables&= ~table->table->map;
    }

    if (prev_table)
    {
      /* The order of tables is reverse: prev_table follows table */
      if (prev_table->straight)
        prev_table->dep_tables|= used_tables;
      if (prev_table->on_expr)
7439
      {
7440
        prev_table->dep_tables|= table->on_expr_dep_tables;
7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452
        table_map prev_used_tables= prev_table->nested_join ?
	                            prev_table->nested_join->used_tables :
	                            prev_table->table->map;
        /* 
          If on expression contains only references to inner tables
          we still make the inner tables dependent on the outer tables.
          It would be enough to set dependency only on one outer table
          for them. Yet this is really a rare case.
	*/  
        if (!(prev_table->on_expr->used_tables() & ~prev_used_tables))
          prev_table->dep_tables|= used_tables;
      }
7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473
    }
    prev_table= table;
  }
    
  /* Flatten nested joins that can be flattened. */
  li.rewind();
  while((table= li++))
  {
    nested_join= table->nested_join;
    if (nested_join && !table->on_expr)
    {
      TABLE_LIST *tbl;
      List_iterator<TABLE_LIST> it(nested_join->join_list);
      while ((tbl= it++))
      {
        tbl->embedding= table->embedding;
        tbl->join_list= table->join_list;
      }      
      li.replace(nested_join->join_list);
    }
  }
unknown's avatar
unknown committed
7474
  DBUG_RETURN(conds); 
7475
}
unknown's avatar
unknown committed
7476
        
unknown's avatar
unknown committed
7477

unknown's avatar
unknown committed
7478
static COND *
unknown's avatar
unknown committed
7479 7480
optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list,
              Item::cond_result *cond_value)
unknown's avatar
unknown committed
7481
{
unknown's avatar
unknown committed
7482
  THD *thd= join->thd;
unknown's avatar
unknown committed
7483
  SELECT_LEX *select= thd->lex->current_select;    
7484 7485
  DBUG_ENTER("optimize_cond");

unknown's avatar
unknown committed
7486 7487
  if (!conds)
    *cond_value= Item::COND_TRUE;
7488 7489
  else
  {
unknown's avatar
unknown committed
7490 7491 7492 7493 7494 7495 7496 7497
    /* 
      Build all multiple equality predicates and eliminate equality
      predicates that can be inferred from these multiple equalities.
      For each reference of a field included into a multiple equality
      that occurs in a function set a pointer to the multiple equality
      predicate. Substitute a constant instead of this field if the
      multiple equality contains a constant.
    */ 
7498
    DBUG_EXECUTE("where", print_where(conds, "original"););
unknown's avatar
unknown committed
7499 7500 7501 7502
    conds= build_equal_items(join->thd, conds, NULL, join_list,
                             &join->cond_equal);
    DBUG_EXECUTE("where",print_where(conds,"after equal_items"););

7503
    /* change field = field to field = const for each found field = const */
7504
    propagate_cond_constants(thd, (I_List<COND_CMP> *) 0, conds, conds);
7505 7506 7507 7508 7509 7510 7511
    /*
      Remove all instances of item == item
      Remove all and-levels where CONST item != CONST item
    */
    DBUG_EXECUTE("where",print_where(conds,"after const change"););
    conds= remove_eq_conds(thd, conds, cond_value) ;
    DBUG_EXECUTE("info",print_where(conds,"after remove"););
unknown's avatar
unknown committed
7512
  }
7513
  DBUG_RETURN(conds);
unknown's avatar
unknown committed
7514 7515 7516 7517
}


/*
7518 7519 7520 7521 7522
  Remove const and eq items. Return new item, or NULL if no condition
  cond_value is set to according:
  COND_OK    query is possible (field = constant)
  COND_TRUE  always true	( 1 = 1 )
  COND_FALSE always false	( 1 = 2 )
unknown's avatar
unknown committed
7523 7524 7525
*/

static COND *
unknown's avatar
af  
unknown committed
7526
remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
unknown's avatar
unknown committed
7527 7528 7529 7530 7531 7532 7533
{
  if (cond->type() == Item::COND_ITEM)
  {
    bool and_level= ((Item_cond*) cond)->functype()
      == Item_func::COND_AND_FUNC;
    List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
    Item::cond_result tmp_cond_value;
7534
    bool should_fix_fields=0;
unknown's avatar
unknown committed
7535 7536 7537 7538 7539

    *cond_value=Item::COND_UNDEF;
    Item *item;
    while ((item=li++))
    {
unknown's avatar
af  
unknown committed
7540
      Item *new_item=remove_eq_conds(thd, item, &tmp_cond_value);
unknown's avatar
unknown committed
7541 7542 7543 7544 7545
      if (!new_item)
	li.remove();
      else if (item != new_item)
      {
	VOID(li.replace(new_item));
7546
	should_fix_fields=1;
unknown's avatar
unknown committed
7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572
      }
      if (*cond_value == Item::COND_UNDEF)
	*cond_value=tmp_cond_value;
      switch (tmp_cond_value) {
      case Item::COND_OK:			// Not TRUE or FALSE
	if (and_level || *cond_value == Item::COND_FALSE)
	  *cond_value=tmp_cond_value;
	break;
      case Item::COND_FALSE:
	if (and_level)
	{
	  *cond_value=tmp_cond_value;
	  return (COND*) 0;			// Always false
	}
	break;
      case Item::COND_TRUE:
	if (!and_level)
	{
	  *cond_value= tmp_cond_value;
	  return (COND*) 0;			// Always true
	}
	break;
      case Item::COND_UNDEF:			// Impossible
	break; /* purecov: deadcode */
      }
    }
7573
    if (should_fix_fields)
unknown's avatar
af  
unknown committed
7574
      cond->update_used_tables();
7575

unknown's avatar
unknown committed
7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589
    if (!((Item_cond*) cond)->argument_list()->elements ||
	*cond_value != Item::COND_OK)
      return (COND*) 0;
    if (((Item_cond*) cond)->argument_list()->elements == 1)
    {						// Remove list
      item= ((Item_cond*) cond)->argument_list()->head();
      ((Item_cond*) cond)->argument_list()->empty();
      return item;
    }
  }
  else if (cond->type() == Item::FUNC_ITEM &&
	   ((Item_func*) cond)->functype() == Item_func::ISNULL_FUNC)
  {
    /*
7590 7591 7592 7593 7594 7595 7596
      Handles this special case for some ODBC applications:
      The are requesting the row that was just updated with a auto_increment
      value with this construct:

      SELECT * from table_name where auto_increment_column IS NULL
      This will be changed to:
      SELECT * from table_name where auto_increment_column = LAST_INSERT_ID
unknown's avatar
unknown committed
7597 7598 7599 7600 7601 7602 7603 7604
    */

    Item_func_isnull *func=(Item_func_isnull*) cond;
    Item **args= func->arguments();
    if (args[0]->type() == Item::FIELD_ITEM)
    {
      Field *field=((Item_field*) args[0])->field;
      if (field->flags & AUTO_INCREMENT_FLAG && !field->table->maybe_null &&
7605 7606
	  (thd->options & OPTION_AUTO_IS_NULL) &&
	  thd->insert_id())
unknown's avatar
unknown committed
7607
      {
7608
#ifdef HAVE_QUERY_CACHE
unknown's avatar
unknown committed
7609
	query_cache_abort(&thd->net);
7610
#endif
unknown's avatar
unknown committed
7611 7612 7613
	COND *new_cond;
	if ((new_cond= new Item_func_eq(args[0],
					new Item_int("last_insert_id()",
7614
						     thd->insert_id(),
unknown's avatar
unknown committed
7615 7616 7617
						     21))))
	{
	  cond=new_cond;
unknown's avatar
unknown committed
7618 7619 7620 7621 7622
          /*
            Item_func_eq can't be fixed after creation so we do not check
            cond->fixed, also it do not need tables so we use 0 as second
            argument.
          */
unknown's avatar
unknown committed
7623
	  cond->fix_fields(thd, 0, &cond);
unknown's avatar
unknown committed
7624
	}
7625
	thd->insert_id(0);		// Clear for next request
unknown's avatar
unknown committed
7626 7627 7628 7629
      }
      /* fix to replace 'NULL' dates with '0' (shreeve@uci.edu) */
      else if (((field->type() == FIELD_TYPE_DATE) ||
		(field->type() == FIELD_TYPE_DATETIME)) &&
7630 7631
		(field->flags & NOT_NULL_FLAG) &&
	       !field->table->maybe_null)
unknown's avatar
unknown committed
7632 7633 7634 7635 7636
      {
	COND *new_cond;
	if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2))))
	{
	  cond=new_cond;
unknown's avatar
unknown committed
7637 7638 7639 7640 7641
          /*
            Item_func_eq can't be fixed after creation so we do not check
            cond->fixed, also it do not need tables so we use 0 as second
            argument.
          */
unknown's avatar
unknown committed
7642
	  cond->fix_fields(thd, 0, &cond);
unknown's avatar
unknown committed
7643 7644 7645
	}
      }
    }
unknown's avatar
unknown committed
7646 7647 7648 7649 7650
    if (cond->const_item())
    {
      *cond_value= eval_const_cond(cond) ? Item::COND_TRUE : Item::COND_FALSE;
      return (COND*) 0;
    }
unknown's avatar
unknown committed
7651 7652 7653 7654 7655 7656 7657 7658 7659 7660
  }
  else if (cond->const_item())
  {
    *cond_value= eval_const_cond(cond) ? Item::COND_TRUE : Item::COND_FALSE;
    return (COND*) 0;
  }
  else if ((*cond_value= cond->eq_cmp_result()) != Item::COND_OK)
  {						// boolan compare function
    Item *left_item=	((Item_func*) cond)->arguments()[0];
    Item *right_item= ((Item_func*) cond)->arguments()[1];
7661
    if (left_item->eq(right_item,1))
unknown's avatar
unknown committed
7662 7663 7664 7665 7666 7667 7668
    {
      if (!left_item->maybe_null ||
	  ((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC)
	return (COND*) 0;			// Compare of identical items
    }
  }
  *cond_value=Item::COND_OK;
7669
  return cond;					// Point at next and level
unknown's avatar
unknown committed
7670 7671 7672
}

/*
7673
  Return 1 if the item is a const value in all the WHERE clause
unknown's avatar
unknown committed
7674 7675 7676 7677 7678 7679 7680 7681 7682
*/

static bool
const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
{
  if (cond->type() == Item::COND_ITEM)
  {
    bool and_level= (((Item_cond*) cond)->functype()
		     == Item_func::COND_AND_FUNC);
unknown's avatar
unknown committed
7683
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705
    Item *item;
    while ((item=li++))
    {
      bool res=const_expression_in_where(item, comp_item, const_item);
      if (res)					// Is a const value
      {
	if (and_level)
	  return 1;
      }
      else if (!and_level)
	return 0;
    }
    return and_level ? 0 : 1;
  }
  else if (cond->eq_cmp_result() != Item::COND_OK)
  {						// boolan compare function
    Item_func* func= (Item_func*) cond;
    if (func->functype() != Item_func::EQUAL_FUNC &&
	func->functype() != Item_func::EQ_FUNC)
      return 0;
    Item *left_item=	((Item_func*) cond)->arguments()[0];
    Item *right_item= ((Item_func*) cond)->arguments()[1];
7706
    if (left_item->eq(comp_item,1))
unknown's avatar
unknown committed
7707 7708 7709 7710
    {
      if (right_item->const_item())
      {
	if (*const_item)
7711
	  return right_item->eq(*const_item, 1);
unknown's avatar
unknown committed
7712 7713 7714 7715
	*const_item=right_item;
	return 1;
      }
    }
7716
    else if (right_item->eq(comp_item,1))
unknown's avatar
unknown committed
7717 7718 7719 7720
    {
      if (left_item->const_item())
      {
	if (*const_item)
7721
	  return left_item->eq(*const_item, 1);
unknown's avatar
unknown committed
7722 7723 7724 7725 7726 7727 7728 7729 7730
	*const_item=left_item;
	return 1;
      }
    }
  }
  return 0;
}

/****************************************************************************
unknown's avatar
unknown committed
7731
  Create internal temporary table
unknown's avatar
unknown committed
7732 7733
****************************************************************************/

7734 7735 7736 7737 7738 7739 7740
/*
  Create field for temporary table from given field
  
  SYNOPSIS
    create_tmp_field_from_field()
    thd			Thread handler
    org_field           field from which new field will be created
7741
    name                New field name
7742
    table		Temporary table
7743 7744 7745
    item	        !=NULL if item->result_field should point to new field.
			This is relevant for how fill_record() is going to work:
			If item != NULL then fill_record() will update
7746
			the record in the original table.
7747
			If item == NULL then fill_record() will update
7748
			the temporary table
7749 7750
    convert_blob_length If >0 create a varstring(convert_blob_length) field 
                        instead of blob.
7751 7752 7753 7754 7755

  RETURN
    0			on error
    new_created field
*/
7756

7757
Field* create_tmp_field_from_field(THD *thd, Field* org_field,
unknown's avatar
Merge  
unknown committed
7758 7759
                                   const char *name, TABLE *table,
                                   Item_field *item, uint convert_blob_length)
7760 7761 7762
{
  Field *new_field;

7763
  if (convert_blob_length && (org_field->flags & BLOB_FLAG))
7764 7765
    new_field= new Field_varstring(convert_blob_length,
                                   org_field->maybe_null(),
7766 7767 7768
                                   org_field->field_name, table,
                                   org_field->charset());
  else
unknown's avatar
unknown committed
7769
    new_field= org_field->new_field(thd->mem_root, table);
7770
  if (new_field)
7771
  {
7772 7773
    if (item)
      item->result_field= new_field;
7774
    else
7775
      new_field->field_name= name;
unknown's avatar
unknown committed
7776
    if (org_field->maybe_null() || (item && item->maybe_null))
7777
      new_field->flags&= ~NOT_NULL_FLAG;	// Because of outer join
7778 7779
    if (org_field->type() == MYSQL_TYPE_VAR_STRING ||
        org_field->type() == MYSQL_TYPE_VARCHAR)
7780
      table->s->db_create_options|= HA_OPTION_PACK_RECORD;
7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801
  }
  return new_field;
}

/*
  Create field for temporary table using type of given item
  
  SYNOPSIS
    create_tmp_field_from_item()
    thd			Thread handler
    item		Item to create a field for
    table		Temporary table
    copy_func		If set and item is a function, store copy of item
			in this array
    modify_item		1 if item->result_field should point to new item.
			This is relevent for how fill_record() is going to
			work:
			If modify_item is 1 then fill_record() will update
			the record in the original table.
			If modify_item is 0 then fill_record() will update
			the temporary table
7802 7803
    convert_blob_length If >0 create a varstring(convert_blob_length) field 
                        instead of blob.
7804 7805 7806 7807 7808

  RETURN
    0			on error
    new_created field
*/
7809 7810

static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
7811 7812
                                         Item ***copy_func, bool modify_item,
                                         uint convert_blob_length)
7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827
{
  bool maybe_null=item->maybe_null;
  Field *new_field;
  LINT_INIT(new_field);

  switch (item->result_type()) {
  case REAL_RESULT:
    new_field=new Field_double(item->max_length, maybe_null,
			       item->name, table, item->decimals);
    break;
  case INT_RESULT:
    new_field=new Field_longlong(item->max_length, maybe_null,
				   item->name, table, item->unsigned_flag);
    break;
  case STRING_RESULT:
7828 7829 7830 7831
    if (item->max_length > 255 && convert_blob_length)
      new_field= new Field_varstring(convert_blob_length, maybe_null,
                                     item->name, table,
                                     item->collation.collation);
7832
    else
7833
      new_field= item->make_string_field(table);
7834
    break;
unknown's avatar
unknown committed
7835 7836 7837 7838 7839 7840 7841
  case DECIMAL_RESULT:
    new_field= new Field_new_decimal(item->max_length - (item->decimals?1:0),
                                     maybe_null,
                                     item->name, table, item->decimals);
    break;
  case ROW_RESULT:
  default:
7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853
    // This case should never be choosen
    DBUG_ASSERT(0);
    new_field= 0; // to satisfy compiler (uninitialized variable)
    break;
  }
  if (copy_func && item->is_result_field())
    *((*copy_func)++) = item;			// Save for copy_funcs
  if (modify_item)
    item->set_result_field(new_field);
  return new_field;
}

7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883

/*
  Create field for information schema table

  SYNOPSIS
    create_tmp_field_for_schema()
    thd			Thread handler
    table		Temporary table
    item		Item to create a field for

  RETURN
    0			on error
    new_created field
*/

Field *create_tmp_field_for_schema(THD *thd, Item *item, TABLE *table)
{
  if (item->field_type() == MYSQL_TYPE_VARCHAR)
  {
    if (item->max_length > MAX_FIELD_VARCHARLENGTH /
        item->collation.collation->mbmaxlen)
      return new Field_blob(item->max_length, item->maybe_null,
                            item->name, table, item->collation.collation);
    return new Field_varstring(item->max_length, item->maybe_null, item->name,
                               table, item->collation.collation);
  }
  return item->tmp_table_field_from_field_type(table);
}


unknown's avatar
unknown committed
7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894
/*
  Create field for temporary table

  SYNOPSIS
    create_tmp_field()
    thd			Thread handler
    table		Temporary table
    item		Item to create a field for
    type		Type of item (normally item->type)
    copy_func		If set and item is a function, store copy of item
			in this array
7895
    from_field          if field will be created using other field as example,
7896
                        pointer example field will be written here
unknown's avatar
unknown committed
7897 7898 7899 7900 7901 7902 7903 7904
    group		1 if we are going to do a relative group by on result
    modify_item		1 if item->result_field should point to new item.
			This is relevent for how fill_record() is going to
			work:
			If modify_item is 1 then fill_record() will update
			the record in the original table.
			If modify_item is 0 then fill_record() will update
			the temporary table
7905 7906
    convert_blob_length If >0 create a varstring(convert_blob_length) field 
                        instead of blob.
7907

unknown's avatar
unknown committed
7908 7909 7910 7911 7912
  RETURN
    0			on error
    new_created field
*/

unknown's avatar
unknown committed
7913
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
7914 7915
                        Item ***copy_func, Field **from_field,
                        bool group, bool modify_item, uint convert_blob_length)
unknown's avatar
unknown committed
7916 7917 7918 7919 7920
{
  switch (type) {
  case Item::SUM_FUNC_ITEM:
  {
    Item_sum *item_sum=(Item_sum*) item;
unknown's avatar
unknown committed
7921 7922 7923 7924
    Field *result= item_sum->create_tmp_field(group, table, convert_blob_length);
    if (!result)
      thd->fatal_error();
    return result;
unknown's avatar
unknown committed
7925 7926
  }
  case Item::FIELD_ITEM:
7927
  case Item::DEFAULT_VALUE_ITEM:
unknown's avatar
af  
unknown committed
7928 7929
  {
    Item_field *field= (Item_field*) item;
7930 7931 7932 7933
    return create_tmp_field_from_field(thd, (*from_field= field->field),
                                       item->name, table,
                                       modify_item ? (Item_field*) item : NULL,
                                       convert_blob_length);
unknown's avatar
af  
unknown committed
7934
  }
unknown's avatar
unknown committed
7935 7936 7937 7938
  case Item::FUNC_ITEM:
  case Item::COND_ITEM:
  case Item::FIELD_AVG_ITEM:
  case Item::FIELD_STD_ITEM:
7939
  case Item::SUBSELECT_ITEM:
unknown's avatar
unknown committed
7940
    /* The following can only happen with 'CREATE TABLE ... SELECT' */
unknown's avatar
unknown committed
7941
  case Item::PROC_ITEM:
unknown's avatar
unknown committed
7942 7943
  case Item::INT_ITEM:
  case Item::REAL_ITEM:
unknown's avatar
unknown committed
7944
  case Item::DECIMAL_ITEM:
unknown's avatar
unknown committed
7945 7946
  case Item::STRING_ITEM:
  case Item::REF_ITEM:
7947
  case Item::NULL_ITEM:
7948
  case Item::VARBIN_ITEM:
7949 7950
    return create_tmp_field_from_item(thd, item, table, copy_func, modify_item,
                                      convert_blob_length);
7951
  case Item::TYPE_HOLDER:
7952
    return ((Item_type_holder *)item)->make_field_by_type(table);
unknown's avatar
unknown committed
7953 7954 7955 7956 7957 7958
  default:					// Dosen't have to be stored
    return 0;
  }
}


unknown's avatar
unknown committed
7959 7960 7961 7962 7963 7964 7965
/*
  Create a temp table according to a field list.
  Set distinct if duplicates could be removed
  Given fields field pointers are changed to point at tmp_table
  for send_fields
*/

7966 7967 7968 7969 7970
#define STRING_TOTAL_LENGTH_TO_PACK_ROWS 128
#define AVG_STRING_LENGTH_TO_PACK_ROWS   64
#define RATIO_TO_PACK_ROWS	       2
#define MIN_STRING_LENGTH_TO_PACK_ROWS   10

unknown's avatar
unknown committed
7971 7972 7973
TABLE *
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
		 ORDER *group, bool distinct, bool save_sum_fields,
7974 7975
		 ulong select_options, ha_rows rows_limit,
		 char *table_alias)
unknown's avatar
unknown committed
7976 7977
{
  TABLE *table;
7978 7979 7980 7981 7982 7983 7984
  uint	i,field_count,null_count,null_pack_length;
  uint  hidden_null_count, hidden_null_pack_length, hidden_field_count;
  uint  blob_count,group_null_items, string_count;
  uint  temp_pool_slot=MY_BIT_NONE;
  ulong reclength, string_total_length;
  bool  using_unique_constraint= 0;
  bool  use_packed_rows= 0;
unknown's avatar
unknown committed
7985
  bool  not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS);
7986
  char	*tmpname,path[FN_REFLEN], filename[FN_REFLEN];
unknown's avatar
unknown committed
7987 7988
  byte	*pos,*group_buff;
  uchar *null_flags;
7989 7990
  Field **reg_field, **from_field;
  uint *blob_field;
unknown's avatar
unknown committed
7991 7992 7993
  Copy_field *copy=0;
  KEY *keyinfo;
  KEY_PART_INFO *key_part_info;
unknown's avatar
unknown committed
7994
  Item **copy_func;
unknown's avatar
unknown committed
7995
  MI_COLUMNDEF *recinfo;
unknown's avatar
unknown committed
7996
  uint total_uneven_bit_length= 0;
unknown's avatar
unknown committed
7997
  DBUG_ENTER("create_tmp_table");
unknown's avatar
unknown committed
7998
  DBUG_PRINT("enter",("distinct: %d  save_sum_fields: %d  rows_limit: %lu  group: %d",
unknown's avatar
unknown committed
7999
		      (int) distinct, (int) save_sum_fields,
unknown's avatar
unknown committed
8000
		      (ulong) rows_limit,test(group)));
unknown's avatar
unknown committed
8001

8002
  statistic_increment(thd->status_var.created_tmp_tables, &LOCK_status);
8003

8004
  if (use_temp_pool)
unknown's avatar
unknown committed
8005
    temp_pool_slot = bitmap_set_next(&temp_pool);
8006 8007

  if (temp_pool_slot != MY_BIT_NONE) // we got a slot
8008 8009
    sprintf(filename, "%s_%lx_%i", tmp_file_prefix,
            current_pid, temp_pool_slot);
8010 8011 8012
  else
  {
    /* if we run out of slots or we are not using tempool */
8013
    sprintf(filename,"%s%lx_%lx_%x",tmp_file_prefix,current_pid,
8014
            thd->thread_id, thd->tmp_table++);
8015
  }
8016

8017 8018 8019 8020
  /*
    No need for change table name to lower case as we are only creating
    MyISAM or HEAP tables here
  */
8021
  sprintf(path, "%s%s", mysql_tmpdir, filename);
8022

unknown's avatar
unknown committed
8023 8024 8025 8026 8027
  if (group)
  {
    if (!param->quick_group)
      group=0;					// Can't use group key
    else for (ORDER *tmp=group ; tmp ; tmp=tmp->next)
8028
    {
unknown's avatar
unknown committed
8029
      (*tmp->item)->marker=4;			// Store null in key
8030
      if ((*tmp->item)->max_length >= CONVERT_IF_BIGGER_TO_BLOB)
8031 8032
	using_unique_constraint=1;
    }
unknown's avatar
unknown committed
8033 8034
    if (param->group_length >= MAX_BLOB_WIDTH)
      using_unique_constraint=1;
unknown's avatar
unknown committed
8035 8036
    if (group)
      distinct=0;				// Can't use distinct
unknown's avatar
unknown committed
8037 8038 8039
  }

  field_count=param->field_count+param->func_count+param->sum_func_count;
unknown's avatar
unknown committed
8040
  hidden_field_count=param->hidden_field_count;
unknown's avatar
unknown committed
8041 8042
  if (!my_multi_malloc(MYF(MY_WME),
		       &table,sizeof(*table),
8043
		       &reg_field,  sizeof(Field*)*(field_count+1),
8044
		       &blob_field, sizeof(uint)*(field_count+1),
8045
		       &from_field, sizeof(Field*)*field_count,
unknown's avatar
unknown committed
8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056
		       &copy_func,sizeof(*copy_func)*(param->func_count+1),
		       &param->keyinfo,sizeof(*param->keyinfo),
		       &key_part_info,
		       sizeof(*key_part_info)*(param->group_parts+1),
		       &param->start_recinfo,
		       sizeof(*param->recinfo)*(field_count*2+4),
		       &tmpname,(uint) strlen(path)+1,
		       &group_buff,group && ! using_unique_constraint ?
		       param->group_length : 0,
		       NullS))
  {
unknown's avatar
unknown committed
8057
    bitmap_clear_bit(&temp_pool, temp_pool_slot);
8058
    DBUG_RETURN(NULL);				/* purecov: inspected */
unknown's avatar
unknown committed
8059 8060 8061
  }
  if (!(param->copy_field=copy=new Copy_field[field_count]))
  {
unknown's avatar
unknown committed
8062
    bitmap_clear_bit(&temp_pool, temp_pool_slot);
8063 8064
    my_free((gptr) table,MYF(0));		/* purecov: inspected */
    DBUG_RETURN(NULL);				/* purecov: inspected */
unknown's avatar
unknown committed
8065
  }
unknown's avatar
unknown committed
8066
  param->items_to_copy= copy_func;
unknown's avatar
unknown committed
8067 8068 8069 8070 8071 8072 8073
  strmov(tmpname,path);
  /* make table according to fields */

  bzero((char*) table,sizeof(*table));
  bzero((char*) reg_field,sizeof(Field*)*(field_count+1));
  bzero((char*) from_field,sizeof(Field*)*field_count);
  table->field=reg_field;
8074
  table->alias= table_alias;
unknown's avatar
unknown committed
8075 8076 8077
  table->reginfo.lock_type=TL_WRITE;	/* Will be updated */
  table->db_stat=HA_OPEN_KEYFILE+HA_OPEN_RNDFILE;
  table->map=1;
8078
  table->temp_pool_slot = temp_pool_slot;
8079
  table->copy_blobs= 1;
8080
  table->in_use= thd;
8081 8082 8083
  table->quick_keys.init();
  table->used_keys.init();
  table->keys_in_use_for_query.init();
unknown's avatar
unknown committed
8084

8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095
  table->s= &table->share_not_to_be_used;
  table->s->blob_field= blob_field;
  table->s->table_name= table->s->path= tmpname;
  table->s->db= "";
  table->s->blob_ptr_size= mi_portable_sizeof_char_ptr;
  table->s->tmp_table= TMP_TABLE;
  table->s->db_low_byte_first=1;                // True for HEAP and MyISAM
  table->s->table_charset= param->table_charset;
  table->s->keys_for_keyread.init();
  table->s->keys_in_use.init();
  /* For easier error reporting */
unknown's avatar
unknown committed
8096
  table->s->table_cache_key= (char*) (table->s->db= "");
8097 8098


unknown's avatar
unknown committed
8099
  /* Calculate which type of fields we will store in the temporary table */
unknown's avatar
unknown committed
8100

8101 8102
  reclength= string_total_length= 0;
  blob_count= string_count= null_count= hidden_null_count= group_null_items= 0;
unknown's avatar
unknown committed
8103
  param->using_indirect_summary_function=0;
unknown's avatar
unknown committed
8104

unknown's avatar
unknown committed
8105
  List_iterator_fast<Item> li(fields);
unknown's avatar
unknown committed
8106 8107
  Item *item;
  Field **tmp_from_field=from_field;
8108
  while ((item=li++))
unknown's avatar
unknown committed
8109 8110
  {
    Item::Type type=item->type();
unknown's avatar
unknown committed
8111
    if (not_all_columns)
unknown's avatar
unknown committed
8112
    {
unknown's avatar
unknown committed
8113 8114 8115 8116 8117 8118 8119 8120 8121 8122
      if (item->with_sum_func && type != Item::SUM_FUNC_ITEM)
      {
	/*
	  Mark that the we have ignored an item that refers to a summary
	  function. We need to know this if someone is going to use
	  DISTINCT on the result.
	*/
	param->using_indirect_summary_function=1;
	continue;
      }
8123
      if (item->const_item() && (int) hidden_field_count <= 0)
8124
        continue; // We don't have to store this
unknown's avatar
unknown committed
8125
    }
unknown's avatar
unknown committed
8126 8127 8128 8129 8130
    if (type == Item::SUM_FUNC_ITEM && !group && !save_sum_fields)
    {						/* Can't calc group yet */
      ((Item_sum*) item)->result_field=0;
      for (i=0 ; i < ((Item_sum*) item)->arg_count ; i++)
      {
8131 8132
	Item **argp= ((Item_sum*) item)->args + i;
	Item *arg= *argp;
unknown's avatar
unknown committed
8133 8134 8135
	if (!arg->const_item())
	{
	  Field *new_field=
8136 8137 8138
            create_tmp_field(thd, table, arg, arg->type(), &copy_func,
                             tmp_from_field, group != 0,not_all_columns,
                             param->convert_blob_length);
unknown's avatar
unknown committed
8139 8140 8141 8142 8143
	  if (!new_field)
	    goto err;					// Should be OOM
	  tmp_from_field++;
	  reclength+=new_field->pack_length();
	  if (new_field->flags & BLOB_FLAG)
8144
	  {
8145
	    *blob_field++= (uint) (reg_field - table->field);
unknown's avatar
unknown committed
8146
	    blob_count++;
8147
	  }
8148
	  *(reg_field++)= new_field;
8149 8150 8151 8152 8153 8154
          if (new_field->real_type() == MYSQL_TYPE_STRING ||
              new_field->real_type() == MYSQL_TYPE_VARCHAR)
          {
            string_count++;
            string_total_length+= new_field->pack_length();
          }
8155
          thd->change_item_tree(argp, new Item_field(new_field));
8156 8157 8158 8159 8160 8161 8162
	  if (!(new_field->flags & NOT_NULL_FLAG))
          {
	    null_count++;
            /*
              new_field->maybe_null() is still false, it will be
              changed below. But we have to setup Item_field correctly
            */
8163
            (*argp)->maybe_null=1;
8164
          }
8165
          new_field->query_id= thd->query_id;
unknown's avatar
unknown committed
8166 8167 8168 8169 8170
	}
      }
    }
    else
    {
unknown's avatar
unknown committed
8171 8172 8173 8174 8175 8176 8177 8178 8179 8180
      /*
	The last parameter to create_tmp_field() is a bit tricky:

	We need to set it to 0 in union, to get fill_record() to modify the
	temporary table.
	We need to set it to 1 on multi-table-update and in select to
	write rows to the temporary table.
	We here distinguish between UNION and multi-table-updates by the fact
	that in the later case group is set to the row pointer.
      */
8181 8182 8183 8184 8185 8186 8187
      Field *new_field= (param->schema_table) ?
        create_tmp_field_for_schema(thd, item, table) :
        create_tmp_field(thd, table, item, type, &copy_func,
                         tmp_from_field, group != 0,
                         not_all_columns || group !=0,
                         param->convert_blob_length);

unknown's avatar
unknown committed
8188 8189
      if (!new_field)
      {
8190
	if (thd->is_fatal_error)
unknown's avatar
unknown committed
8191 8192 8193 8194 8195 8196 8197 8198 8199
	  goto err;				// Got OOM
	continue;				// Some kindf of const item
      }
      if (type == Item::SUM_FUNC_ITEM)
	((Item_sum *) item)->result_field= new_field;
      tmp_from_field++;
      reclength+=new_field->pack_length();
      if (!(new_field->flags & NOT_NULL_FLAG))
	null_count++;
unknown's avatar
unknown committed
8200 8201
      if (new_field->type() == FIELD_TYPE_BIT)
        total_uneven_bit_length+= new_field->field_length & 7;
unknown's avatar
unknown committed
8202
      if (new_field->flags & BLOB_FLAG)
8203
      {
8204
        *blob_field++= (uint) (reg_field - table->field);
unknown's avatar
unknown committed
8205
	blob_count++;
8206
      }
unknown's avatar
unknown committed
8207 8208 8209 8210 8211
      if (item->marker == 4 && item->maybe_null)
      {
	group_null_items++;
	new_field->flags|= GROUP_FLAG;
      }
8212
      new_field->query_id= thd->query_id;
unknown's avatar
unknown committed
8213 8214
      *(reg_field++) =new_field;
    }
unknown's avatar
unknown committed
8215 8216
    if (!--hidden_field_count)
      hidden_null_count=null_count;
unknown's avatar
unknown committed
8217
  }
8218
  DBUG_ASSERT(field_count >= (uint) (reg_field - table->field));
unknown's avatar
unknown committed
8219
  field_count= (uint) (reg_field - table->field);
8220
  *blob_field= 0;				// End marker
unknown's avatar
unknown committed
8221 8222

  /* If result table is small; use a heap */
8223
  if (blob_count || using_unique_constraint ||
unknown's avatar
unknown committed
8224 8225 8226
      (select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
      OPTION_BIG_TABLES)
  {
8227
    table->file=get_new_handler(table,table->s->db_type= DB_TYPE_MYISAM);
unknown's avatar
unknown committed
8228 8229 8230 8231 8232 8233 8234
    if (group &&
	(param->group_parts > table->file->max_key_parts() ||
	 param->group_length > table->file->max_key_length()))
      using_unique_constraint=1;
  }
  else
  {
8235
    table->file=get_new_handler(table,table->s->db_type= DB_TYPE_HEAP);
unknown's avatar
unknown committed
8236 8237 8238 8239 8240
  }

  if (!using_unique_constraint)
    reclength+= group_null_items;	// null flag is stored separately

8241
  table->s->blob_fields= blob_count;
unknown's avatar
unknown committed
8242
  if (blob_count == 0)
unknown's avatar
unknown committed
8243 8244
  {
    /* We need to ensure that first byte is not 0 for the delete link */
8245
    if (param->hidden_field_count)
unknown's avatar
unknown committed
8246 8247 8248 8249 8250
      hidden_null_count++;
    else
      null_count++;
  }
  hidden_null_pack_length=(hidden_null_count+7)/8;
unknown's avatar
unknown committed
8251 8252
  null_pack_length= hidden_null_count +
                    (null_count + total_uneven_bit_length + 7) / 8;
unknown's avatar
unknown committed
8253
  reclength+=null_pack_length;
unknown's avatar
unknown committed
8254 8255
  if (!reclength)
    reclength=1;				// Dummy select
8256 8257 8258 8259 8260 8261
  /* Use packed rows if there is blobs or a lot of space to gain */
  if (blob_count ||
      string_total_length >= STRING_TOTAL_LENGTH_TO_PACK_ROWS &&
      (reclength / string_total_length <= RATIO_TO_PACK_ROWS ||
       string_total_length / string_count >= AVG_STRING_LENGTH_TO_PACK_ROWS))
    use_packed_rows= 1;
unknown's avatar
unknown committed
8262

8263 8264
  table->s->fields= field_count;
  table->s->reclength= reclength;
unknown's avatar
unknown committed
8265 8266
  {
    uint alloc_length=ALIGN_SIZE(reclength+MI_UNIQUE_HASH_LENGTH+1);
8267
    table->s->rec_buff_length= alloc_length;
unknown's avatar
unknown committed
8268
    if (!(table->record[0]= (byte *) my_malloc(alloc_length*3, MYF(MY_WME))))
unknown's avatar
unknown committed
8269
      goto err;
unknown's avatar
unknown committed
8270
    table->record[1]= table->record[0]+alloc_length;
8271
    table->s->default_values= table->record[1]+alloc_length;
unknown's avatar
unknown committed
8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 8284
  }
  copy_func[0]=0;				// End marker

  recinfo=param->start_recinfo;
  null_flags=(uchar*) table->record[0];
  pos=table->record[0]+ null_pack_length;
  if (null_pack_length)
  {
    bzero((byte*) recinfo,sizeof(*recinfo));
    recinfo->type=FIELD_NORMAL;
    recinfo->length=null_pack_length;
    recinfo++;
    bfill(null_flags,null_pack_length,255);	// Set null fields
8285 8286

    table->null_flags= (uchar*) table->record[0];
8287 8288
    table->s->null_fields= null_count+ hidden_null_count;
    table->s->null_bytes= null_pack_length;
unknown's avatar
unknown committed
8289 8290
  }
  null_count= (blob_count == 0) ? 1 : 0;
unknown's avatar
unknown committed
8291
  hidden_field_count=param->hidden_field_count;
unknown's avatar
unknown committed
8292 8293 8294 8295 8296 8297 8298 8299 8300 8301
  for (i=0,reg_field=table->field; i < field_count; i++,reg_field++,recinfo++)
  {
    Field *field= *reg_field;
    uint length;
    bzero((byte*) recinfo,sizeof(*recinfo));

    if (!(field->flags & NOT_NULL_FLAG))
    {
      if (field->flags & GROUP_FLAG && !using_unique_constraint)
      {
8302 8303 8304 8305
	/*
	  We have to reserve one byte here for NULL bits,
	  as this is updated by 'end_update()'
	*/
unknown's avatar
unknown committed
8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335
	*pos++=0;				// Null is stored here
	recinfo->length=1;
	recinfo->type=FIELD_NORMAL;
	recinfo++;
	bzero((byte*) recinfo,sizeof(*recinfo));
      }
      else
      {
	recinfo->null_bit= 1 << (null_count & 7);
	recinfo->null_pos= null_count/8;
      }
      field->move_field((char*) pos,null_flags+null_count/8,
			1 << (null_count & 7));
      null_count++;
    }
    else
      field->move_field((char*) pos,(uchar*) 0,0);
    field->reset();
    if (from_field[i])
    {						/* Not a table Item */
      copy->set(field,from_field[i],save_sum_fields);
      copy++;
    }
    length=field->pack_length();
    pos+= length;

    /* Make entry for create table */
    recinfo->length=length;
    if (field->flags & BLOB_FLAG)
      recinfo->type= (int) FIELD_BLOB;
8336 8337 8338
    else if (use_packed_rows &&
             field->real_type() == MYSQL_TYPE_STRING &&
	     length >= MIN_STRING_LENGTH_TO_PACK_ROWS)
unknown's avatar
unknown committed
8339
      recinfo->type=FIELD_SKIP_ENDSPACE;
unknown's avatar
unknown committed
8340 8341
    else
      recinfo->type=FIELD_NORMAL;
unknown's avatar
unknown committed
8342 8343
    if (!--hidden_field_count)
      null_count=(null_count+7) & ~7;		// move to next byte
8344 8345

    // fix table name in field entry
8346
    field->table_name= &table->alias;
unknown's avatar
unknown committed
8347 8348
  }

unknown's avatar
unknown committed
8349
  param->copy_field_end=copy;
unknown's avatar
unknown committed
8350
  param->recinfo=recinfo;
8351
  store_record(table,s->default_values);        // Make empty default record
unknown's avatar
unknown committed
8352

8353
  if (thd->variables.tmp_table_size == ~(ulong) 0)		// No limit
8354
    table->s->max_rows= ~(ha_rows) 0;
8355
  else
8356 8357 8358 8359 8360 8361
    table->s->max_rows= (((table->s->db_type == DB_TYPE_HEAP) ?
                          min(thd->variables.tmp_table_size,
                              thd->variables.max_heap_table_size) :
                          thd->variables.tmp_table_size)/ table->s->reclength);
  set_if_bigger(table->s->max_rows,1);		// For dummy start options
  keyinfo= param->keyinfo;
unknown's avatar
unknown committed
8362 8363 8364 8365 8366 8367

  if (group)
  {
    DBUG_PRINT("info",("Creating group key in temporary table"));
    table->group=group;				/* Table is grouped by key */
    param->group_buff=group_buff;
8368 8369
    table->s->keys=1;
    table->s->uniques= test(using_unique_constraint);
unknown's avatar
unknown committed
8370 8371 8372 8373 8374 8375
    table->key_info=keyinfo;
    keyinfo->key_part=key_part_info;
    keyinfo->flags=HA_NOSAME;
    keyinfo->usable_key_parts=keyinfo->key_parts= param->group_parts;
    keyinfo->key_length=0;
    keyinfo->rec_per_key=0;
8376
    keyinfo->algorithm= HA_KEY_ALG_UNDEF;
unknown's avatar
unknown committed
8377
    keyinfo->name= (char*) "group_key";
unknown's avatar
unknown committed
8378 8379
    for (; group ; group=group->next,key_part_info++)
    {
8380
      Field *field=(*group->item)->get_tmp_table_field();
unknown's avatar
unknown committed
8381
      bool maybe_null=(*group->item)->maybe_null;
8382
      key_part_info->null_bit=0;
unknown's avatar
unknown committed
8383 8384
      key_part_info->field=  field;
      key_part_info->offset= field->offset();
8385
      key_part_info->length= (uint16) field->key_length();
unknown's avatar
unknown committed
8386 8387 8388
      key_part_info->type=   (uint8) field->key_type();
      key_part_info->key_type =
	((ha_base_keytype) key_part_info->type == HA_KEYTYPE_TEXT ||
8389 8390
	 (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT1 ||
	 (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT2) ?
unknown's avatar
unknown committed
8391 8392 8393 8394
	0 : FIELDFLAG_BINARY;
      if (!using_unique_constraint)
      {
	group->buff=(char*) group_buff;
unknown's avatar
unknown committed
8395 8396 8397 8398 8399
	if (!(group->field= field->new_key_field(thd->mem_root,table,
                                                 (char*) group_buff +
                                                 test(maybe_null),
                                                 field->null_ptr,
                                                 field->null_bit)))
unknown's avatar
unknown committed
8400 8401 8402 8403
	  goto err; /* purecov: inspected */
	if (maybe_null)
	{
	  /*
unknown's avatar
unknown committed
8404 8405
	    To be able to group on NULL, we reserved place in group_buff
	    for the NULL flag just before the column. (see above).
8406
	    The field data is after this flag.
unknown's avatar
unknown committed
8407
	    The NULL flag is updated in 'end_update()' and 'end_write()'
unknown's avatar
unknown committed
8408
	  */
8409 8410 8411 8412
	  keyinfo->flags|= HA_NULL_ARE_EQUAL;	// def. that NULL == NULL
	  key_part_info->null_bit=field->null_bit;
	  key_part_info->null_offset= (uint) (field->null_ptr -
					      (uchar*) table->record[0]);
unknown's avatar
unknown committed
8413 8414
          group->buff++;                        // Pointer to field data
	  group_buff++;                         // Skipp null flag
unknown's avatar
unknown committed
8415
	}
8416 8417
        /* In GROUP BY 'a' and 'a ' are equal for VARCHAR fields */
        key_part_info->key_part_flag|= HA_END_SPACE_ARE_EQUAL;
8418
	group_buff+= group->field->pack_length();
unknown's avatar
unknown committed
8419 8420 8421 8422 8423
      }
      keyinfo->key_length+=  key_part_info->length;
    }
  }

unknown's avatar
unknown committed
8424
  if (distinct)
unknown's avatar
unknown committed
8425
  {
unknown's avatar
unknown committed
8426 8427 8428 8429 8430 8431
    /*
      Create an unique key or an unique constraint over all columns
      that should be in the result.  In the temporary table, there are
      'param->hidden_field_count' extra columns, whose null bits are stored
      in the first 'hidden_null_pack_length' bytes of the row.
    */
8432 8433
    DBUG_PRINT("info",("hidden_field_count: %d", param->hidden_field_count));

unknown's avatar
unknown committed
8434
    null_pack_length-=hidden_null_pack_length;
unknown's avatar
unknown committed
8435
    keyinfo->key_parts= ((field_count-param->hidden_field_count)+
8436
			 test(null_pack_length));
8437
    set_if_smaller(table->s->max_rows, rows_limit);
unknown's avatar
unknown committed
8438
    param->end_write_records= rows_limit;
8439 8440
    table->distinct= 1;
    table->s->keys= 1;
unknown's avatar
unknown committed
8441 8442 8443
    if (blob_count)
    {
      using_unique_constraint=1;
8444
      table->s->uniques= 1;
unknown's avatar
unknown committed
8445 8446 8447 8448 8449 8450
    }
    if (!(key_part_info= (KEY_PART_INFO*)
	  sql_calloc((keyinfo->key_parts)*sizeof(KEY_PART_INFO))))
      goto err;
    table->key_info=keyinfo;
    keyinfo->key_part=key_part_info;
8451
    keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL;
unknown's avatar
unknown committed
8452
    keyinfo->key_length=(uint16) reclength;
unknown's avatar
unknown committed
8453
    keyinfo->name= (char*) "distinct_key";
8454
    keyinfo->algorithm= HA_KEY_ALG_UNDEF;
8455
    keyinfo->rec_per_key=0;
unknown's avatar
unknown committed
8456
    if (null_pack_length)
unknown's avatar
unknown committed
8457
    {
8458
      key_part_info->null_bit=0;
unknown's avatar
unknown committed
8459 8460
      key_part_info->offset=hidden_null_pack_length;
      key_part_info->length=null_pack_length;
unknown's avatar
unknown committed
8461 8462 8463 8464 8465
      key_part_info->field=new Field_string((char*) table->record[0],
					    (uint32) key_part_info->length,
					    (uchar*) 0,
					    (uint) 0,
					    Field::NONE,
unknown's avatar
unknown committed
8466
					    NullS, table, &my_charset_bin);
unknown's avatar
unknown committed
8467 8468 8469 8470
      key_part_info->key_type=FIELDFLAG_BINARY;
      key_part_info->type=    HA_KEYTYPE_BINARY;
      key_part_info++;
    }
8471
    /* Create a distinct key over the columns we are going to return */
unknown's avatar
unknown committed
8472 8473
    for (i=param->hidden_field_count, reg_field=table->field + i ;
	 i < field_count;
unknown's avatar
unknown committed
8474 8475
	 i++, reg_field++, key_part_info++)
    {
8476
      key_part_info->null_bit=0;
unknown's avatar
unknown committed
8477 8478 8479 8480 8481 8482
      key_part_info->field=    *reg_field;
      key_part_info->offset=   (*reg_field)->offset();
      key_part_info->length=   (uint16) (*reg_field)->pack_length();
      key_part_info->type=     (uint8) (*reg_field)->key_type();
      key_part_info->key_type =
	((ha_base_keytype) key_part_info->type == HA_KEYTYPE_TEXT ||
8483 8484
	 (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT1 ||
	 (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT2) ?
unknown's avatar
unknown committed
8485 8486 8487
	0 : FIELDFLAG_BINARY;
    }
  }
8488
  if (thd->is_fatal_error)				// If end of memory
unknown's avatar
unknown committed
8489
    goto err;					 /* purecov: inspected */
8490 8491
  table->s->db_record_offset= 1;
  if (table->s->db_type == DB_TYPE_MYISAM)
unknown's avatar
unknown committed
8492 8493 8494 8495 8496 8497 8498 8499
  {
    if (create_myisam_tmp_table(table,param,select_options))
      goto err;
  }
  if (!open_tmp_table(table))
    DBUG_RETURN(table);

 err:
8500
  free_tmp_table(thd,table);                    /* purecov: inspected */
unknown's avatar
unknown committed
8501
  bitmap_clear_bit(&temp_pool, temp_pool_slot);
unknown's avatar
unknown committed
8502 8503 8504 8505
  DBUG_RETURN(NULL);				/* purecov: inspected */
}


8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559 8560 8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571 8572 8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 8614 8615 8616
/****************************************************************************/

/*
  Create a reduced TABLE object with properly set up Field list from a
  list of field definitions.

  SYNOPSIS
    create_virtual_tmp_table()
      thd         connection handle
      field_list  list of column definitions

  DESCRIPTION
    The created table doesn't have a table handler assotiated with
    it, has no keys, no group/distinct, no copy_funcs array.
    The sole purpose of this TABLE object is to use the power of Field
    class to read/write data to/from table->record[0]. Then one can store
    the record in any container (RB tree, hash, etc).
    The table is created in THD mem_root, so are the table's fields.
    Consequently, if you don't BLOB fields, you don't need to free it.

  RETURN
    0 if out of memory, TABLE object in case of success
*/

TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list)
{
  uint field_count= field_list.elements;
  Field **field;
  create_field *cdef;                           /* column definition */
  uint record_length= 0;
  uint null_count= 0;                 /* number of columns which may be null */
  uint null_pack_length;              /* NULL representation array length */
  TABLE_SHARE *s;
  /* Create the table and list of all fields */
  TABLE *table= (TABLE*) thd->calloc(sizeof(*table));
  field= (Field**) thd->alloc((field_count + 1) * sizeof(Field*));
  if (!table || !field)
    return 0;

  table->field= field;
  table->s= s= &table->share_not_to_be_used;
  s->fields= field_count;

  /* Create all fields and calculate the total length of record */
  List_iterator_fast<create_field> it(field_list);
  while ((cdef= it++))
  {
    *field= make_field(0, cdef->length,
                       (uchar*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
                       f_maybe_null(cdef->pack_flag) ? 1 : 0,
                       cdef->pack_flag, cdef->sql_type, cdef->charset,
                       cdef->geom_type, cdef->unireg_check,
                       cdef->interval, cdef->field_name, table);
    if (!*field)
      goto error;
    record_length+= (**field).pack_length();
    if (! ((**field).flags & NOT_NULL_FLAG))
      ++null_count;
    ++field;
  }
  *field= NULL;                                 /* mark the end of the list */

  null_pack_length= (null_count + 7)/8;
  s->reclength= record_length + null_pack_length;
  s->rec_buff_length= ALIGN_SIZE(s->reclength + 1);
  table->record[0]= (byte*) thd->alloc(s->rec_buff_length);
  if (!table->record[0])
    goto error;

  if (null_pack_length)
  {
    table->null_flags= (uchar*) table->record[0];
    s->null_fields= null_count;
    s->null_bytes= null_pack_length;
  }

  table->in_use= thd;           /* field->reset() may access table->in_use */
  {
    /* Set up field pointers */
    byte *null_pos= table->record[0];
    byte *field_pos= null_pos + s->null_bytes;
    uint null_bit= 1;

    for (field= table->field; *field; ++field)
    {
      Field *cur_field= *field;
      if ((cur_field->flags & NOT_NULL_FLAG))
        cur_field->move_field((char*) field_pos);
      else
      {
        cur_field->move_field((char*) field_pos, (uchar*) null_pos, null_bit);
        null_bit<<= 1;
        if (null_bit == (1 << 8))
        {
          ++null_pos;
          null_bit= 1;
        }
      }
      cur_field->reset();

      field_pos+= cur_field->pack_length();
    }
  }
  return table;
error:
  for (field= table->field; *field; ++field)
    delete *field;                         /* just invokes field destructor */
  return 0;
}


unknown's avatar
unknown committed
8617 8618 8619
static bool open_tmp_table(TABLE *table)
{
  int error;
8620 8621
  if ((error=table->file->ha_open(table->s->table_name,O_RDWR,
                                  HA_OPEN_TMP_TABLE)))
unknown's avatar
unknown committed
8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632
  {
    table->file->print_error(error,MYF(0)); /* purecov: inspected */
    table->db_stat=0;
    return(1);
  }
  (void) table->file->extra(HA_EXTRA_QUICK);		/* Faster */
  return(0);
}


static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
8633
				    ulong options)
unknown's avatar
unknown committed
8634 8635 8636 8637 8638 8639
{
  int error;
  MI_KEYDEF keydef;
  MI_UNIQUEDEF uniquedef;
  KEY *keyinfo=param->keyinfo;
  DBUG_ENTER("create_myisam_tmp_table");
8640

8641
  if (table->s->keys)
unknown's avatar
unknown committed
8642 8643
  {						// Get keys for ni_create
    bool using_unique_constraint=0;
unknown's avatar
unknown committed
8644
    HA_KEYSEG *seg= (HA_KEYSEG*) sql_calloc(sizeof(*seg) *
unknown's avatar
unknown committed
8645 8646 8647 8648 8649 8650
					    keyinfo->key_parts);
    if (!seg)
      goto err;

    if (keyinfo->key_length >= table->file->max_key_length() ||
	keyinfo->key_parts > table->file->max_key_parts() ||
8651
	table->s->uniques)
unknown's avatar
unknown committed
8652 8653
    {
      /* Can't create a key; Make a unique constraint instead of a key */
8654 8655
      table->s->keys=    0;
      table->s->uniques= 1;
unknown's avatar
unknown committed
8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666
      using_unique_constraint=1;
      bzero((char*) &uniquedef,sizeof(uniquedef));
      uniquedef.keysegs=keyinfo->key_parts;
      uniquedef.seg=seg;
      uniquedef.null_are_equal=1;

      /* Create extra column for hash value */
      bzero((byte*) param->recinfo,sizeof(*param->recinfo));
      param->recinfo->type= FIELD_CHECK;
      param->recinfo->length=MI_UNIQUE_HASH_LENGTH;
      param->recinfo++;
8667
      table->s->reclength+=MI_UNIQUE_HASH_LENGTH;
unknown's avatar
unknown committed
8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679
    }
    else
    {
      /* Create an unique key */
      bzero((char*) &keydef,sizeof(keydef));
      keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
      keydef.keysegs=  keyinfo->key_parts;
      keydef.seg= seg;
    }
    for (uint i=0; i < keyinfo->key_parts ; i++,seg++)
    {
      Field *field=keyinfo->key_part[i].field;
8680
      seg->flag=     0;
unknown's avatar
unknown committed
8681
      seg->language= field->charset()->number;
8682 8683
      seg->length=   keyinfo->key_part[i].length;
      seg->start=    keyinfo->key_part[i].offset;
unknown's avatar
unknown committed
8684 8685 8686 8687
      if (field->flags & BLOB_FLAG)
      {
	seg->type=
	((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
8688
	 HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
8689
	seg->bit_start= (uint8)(field->pack_length() - table->s->blob_ptr_size);
unknown's avatar
unknown committed
8690 8691 8692 8693 8694
	seg->flag= HA_BLOB_PART;
	seg->length=0;			// Whole blob in unique constraint
      }
      else
      {
8695
	seg->type= keyinfo->key_part[i].type;
8696 8697
        /* Tell handler if it can do suffic space compression */
	if (field->real_type() == MYSQL_TYPE_STRING &&
unknown's avatar
unknown committed
8698
	    keyinfo->key_part[i].length > 4)
8699
	  seg->flag|= HA_SPACE_PACK;
unknown's avatar
unknown committed
8700
      }
8701
      if (!(field->flags & NOT_NULL_FLAG))
unknown's avatar
unknown committed
8702 8703 8704
      {
	seg->null_bit= field->null_bit;
	seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]);
8705 8706 8707
	/*
	  We are using a GROUP BY on something that contains NULL
	  In this case we have to tell MyISAM that two NULL should
8708
	  on INSERT be regarded at the same value
8709 8710 8711
	*/
	if (!using_unique_constraint)
	  keydef.flag|= HA_NULL_ARE_EQUAL;
unknown's avatar
unknown committed
8712 8713 8714 8715 8716
      }
    }
  }
  MI_CREATE_INFO create_info;
  bzero((char*) &create_info,sizeof(create_info));
unknown's avatar
unknown committed
8717

8718 8719
  if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
      OPTION_BIG_TABLES)
unknown's avatar
unknown committed
8720 8721
    create_info.data_file_length= ~(ulonglong) 0;

8722
  if ((error=mi_create(table->s->table_name,table->s->keys,&keydef,
unknown's avatar
unknown committed
8723 8724
		       (uint) (param->recinfo-param->start_recinfo),
		       param->start_recinfo,
8725
		       table->s->uniques, &uniquedef,
unknown's avatar
unknown committed
8726 8727 8728 8729 8730 8731 8732
		       &create_info,
		       HA_CREATE_TMP_TABLE)))
  {
    table->file->print_error(error,MYF(0));	/* purecov: inspected */
    table->db_stat=0;
    goto err;
  }
8733 8734
  statistic_increment(table->in_use->status_var.created_tmp_disk_tables,
		      &LOCK_status);
8735
  table->s->db_record_offset= 1;
unknown's avatar
unknown committed
8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746
  DBUG_RETURN(0);
 err:
  DBUG_RETURN(1);
}


void
free_tmp_table(THD *thd, TABLE *entry)
{
  const char *save_proc_info;
  DBUG_ENTER("free_tmp_table");
8747
  DBUG_PRINT("enter",("table: %s",entry->alias));
unknown's avatar
unknown committed
8748 8749 8750

  save_proc_info=thd->proc_info;
  thd->proc_info="removing tmp table";
8751
  free_blobs(entry);
unknown's avatar
af  
unknown committed
8752
  if (entry->file)
unknown's avatar
unknown committed
8753
  {
unknown's avatar
af  
unknown committed
8754 8755 8756 8757 8758 8759 8760 8761 8762
    if (entry->db_stat)
    {
      (void) entry->file->close();
    }
    /*
      We can't call ha_delete_table here as the table may created in mixed case
      here and we have to ensure that delete_table gets the table name in
      the original case.
    */
8763 8764 8765
    if (!(test_flags & TEST_KEEP_TMP_TABLES) ||
        entry->s->db_type == DB_TYPE_HEAP)
      entry->file->delete_table(entry->s->table_name);
unknown's avatar
unknown committed
8766 8767
    delete entry->file;
  }
unknown's avatar
af  
unknown committed
8768

unknown's avatar
unknown committed
8769 8770
  /* free blobs */
  for (Field **ptr=entry->field ; *ptr ; ptr++)
8771
    (*ptr)->free();
unknown's avatar
unknown committed
8772 8773
  my_free((gptr) entry->record[0],MYF(0));
  free_io_cache(entry);
8774

unknown's avatar
unknown committed
8775
  bitmap_clear_bit(&temp_pool, entry->temp_pool_slot);
8776

unknown's avatar
unknown committed
8777 8778 8779 8780 8781 8782 8783 8784 8785 8786
  my_free((gptr) entry,MYF(0));
  thd->proc_info=save_proc_info;

  DBUG_VOID_RETURN;
}

/*
* If a HEAP table gets full, create a MyISAM table and copy all rows to this
*/

unknown's avatar
unknown committed
8787 8788
bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
			     int error, bool ignore_last_dupp_key_error)
unknown's avatar
unknown committed
8789 8790 8791 8792 8793 8794
{
  TABLE new_table;
  const char *save_proc_info;
  int write_err;
  DBUG_ENTER("create_myisam_from_heap");

8795
  if (table->s->db_type != DB_TYPE_HEAP || error != HA_ERR_RECORD_FILE_FULL)
unknown's avatar
unknown committed
8796 8797 8798 8799 8800
  {
    table->file->print_error(error,MYF(0));
    DBUG_RETURN(1);
  }
  new_table= *table;
8801 8802 8803
  new_table.s= &new_table.share_not_to_be_used;
  new_table.s->db_type= DB_TYPE_MYISAM;
  if (!(new_table.file= get_new_handler(&new_table,DB_TYPE_MYISAM)))
unknown's avatar
unknown committed
8804 8805 8806 8807 8808 8809
    DBUG_RETURN(1);				// End of memory

  save_proc_info=thd->proc_info;
  thd->proc_info="converting HEAP to MyISAM";

  if (create_myisam_tmp_table(&new_table,param,
unknown's avatar
unknown committed
8810
			      thd->lex->select_lex.options | thd->options))
unknown's avatar
unknown committed
8811 8812 8813
    goto err2;
  if (open_tmp_table(&new_table))
    goto err1;
unknown's avatar
af  
unknown committed
8814 8815
  if (table->file->indexes_are_disabled())
    new_table.file->disable_indexes(HA_KEY_SWITCH_ALL);
unknown's avatar
unknown committed
8816
  table->file->ha_index_or_rnd_end();
8817
  table->file->ha_rnd_init(1);
8818 8819
  if (table->no_rows)
  {
8820 8821
    new_table.file->extra(HA_EXTRA_NO_ROWS);
    new_table.no_rows=1;
8822 8823
  }

8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835
#ifdef TO_BE_DONE_LATER_IN_4_1
  /*
    To use start_bulk_insert() (which is new in 4.1) we need to find
    all places where a corresponding end_bulk_insert() should be put.
  */
  table->file->info(HA_STATUS_VARIABLE); /* update table->file->records */
  new_table.file->start_bulk_insert(table->file->records);
#else
  /* HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it */
  new_table.file->extra(HA_EXTRA_WRITE_CACHE);
#endif

unknown's avatar
unknown committed
8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850
  /* copy all old rows */
  while (!table->file->rnd_next(new_table.record[1]))
  {
    if ((write_err=new_table.file->write_row(new_table.record[1])))
      goto err;
  }
  /* copy row that filled HEAP table */
  if ((write_err=new_table.file->write_row(table->record[0])))
  {
    if (write_err != HA_ERR_FOUND_DUPP_KEY &&
	write_err != HA_ERR_FOUND_DUPP_UNIQUE || !ignore_last_dupp_key_error)
    goto err;
  }

  /* remove heap table and change to use myisam table */
unknown's avatar
unknown committed
8851
  (void) table->file->ha_rnd_end();
unknown's avatar
unknown committed
8852
  (void) table->file->close();
8853
  (void) table->file->delete_table(table->s->table_name);
unknown's avatar
unknown committed
8854 8855
  delete table->file;
  table->file=0;
8856 8857
  *table= new_table;
  table->s= &table->share_not_to_be_used;
unknown's avatar
unknown committed
8858
  table->file->change_table_ptr(table);
8859 8860 8861
  if (save_proc_info)
    thd->proc_info= (!strcmp(save_proc_info,"Copying to tmp table") ?
                     "Copying to tmp table on disk" : save_proc_info);
unknown's avatar
unknown committed
8862 8863 8864 8865 8866
  DBUG_RETURN(0);

 err:
  DBUG_PRINT("error",("Got error: %d",write_err));
  table->file->print_error(error,MYF(0));	// Give table is full error
unknown's avatar
unknown committed
8867
  (void) table->file->ha_rnd_end();
unknown's avatar
unknown committed
8868 8869
  (void) new_table.file->close();
 err1:
8870
  new_table.file->delete_table(new_table.s->table_name);
unknown's avatar
unknown committed
8871 8872 8873 8874 8875 8876 8877
  delete new_table.file;
 err2:
  thd->proc_info=save_proc_info;
  DBUG_RETURN(1);
}


8878 8879 8880 8881
/*
  SYNOPSIS
    setup_end_select_func()
    join   join to setup the function for.
unknown's avatar
unknown committed
8882

8883 8884 8885 8886
  DESCRIPTION
    Rows produced by a join sweep may end up in a temporary table or be sent
    to a client. Setup the function of the nested loop join algorithm which
    handles final fully constructed and matched records.
unknown's avatar
unknown committed
8887

8888 8889 8890
  RETURN
    end_select function to use. This function can't fail.
*/
unknown's avatar
unknown committed
8891

8892 8893 8894 8895
static Next_select_func setup_end_select_func(JOIN *join)
{
  TABLE *table= join->tmp_table;
  Next_select_func end_select;
unknown's avatar
unknown committed
8896 8897 8898 8899 8900
  /* Set up select_end */
  if (table)
  {
    if (table->group && join->tmp_table_param.sum_func_count)
    {
8901
      if (table->s->keys)
unknown's avatar
unknown committed
8902
      {
8903
	DBUG_PRINT("info",("Using end_update"));
unknown's avatar
unknown committed
8904 8905 8906
	end_select=end_update;
      }
      else
8907 8908
      {
	DBUG_PRINT("info",("Using end_unique_update"));
unknown's avatar
unknown committed
8909
	end_select=end_unique_update;
8910
      }
unknown's avatar
unknown committed
8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924
    }
    else if (join->sort_and_group)
    {
      DBUG_PRINT("info",("Using end_write_group"));
      end_select=end_write_group;
    }
    else
    {
      DBUG_PRINT("info",("Using end_write"));
      end_select=end_write;
    }
  }
  else
  {
8925 8926 8927 8928 8929 8930 8931 8932 8933 8934
    /* Test if data is accessed via QUICK_GROUP_MIN_MAX_SELECT. */
    bool is_using_quick_group_min_max_select=
      (join->join_tab->select && join->join_tab->select->quick &&
       (join->join_tab->select->quick->get_type() ==
        QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX));

    if ((join->sort_and_group ||
         (join->procedure && join->procedure->flags & PROC_GROUP)) &&
        !is_using_quick_group_min_max_select)
      end_select= end_send_group;
unknown's avatar
unknown committed
8935
    else
8936
      end_select= end_send;
unknown's avatar
unknown committed
8937
  }
8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969
  return end_select;
}


/****************************************************************************
  Make a join of all tables and write it on socket or to table
  Return:  0 if ok
           1 if error is sent
          -1 if error should be sent
****************************************************************************/

static int
do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
{
  int error= 0;
  JOIN_TAB *join_tab;
  DBUG_ENTER("do_select");

  join->procedure=procedure;
  join->tmp_table= table;			/* Save for easy recursion */
  join->fields= fields;

  if (table)
  {
    VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
    empty_record(table);
    if (table->group && join->tmp_table_param.sum_func_count &&
        table->s->keys && !table->file->inited)
      table->file->ha_index_init(0);
  }
  /* Set up select_end */
  join->join_tab[join->tables-1].next_select= setup_end_select_func(join);
unknown's avatar
unknown committed
8970 8971 8972 8973 8974

  join_tab=join->join_tab+join->const_tables;
  join->send_records=0;
  if (join->tables == join->const_tables)
  {
8975
    /*
8976
      HAVING will be checked after processing aggregate functions,
8977 8978
      But WHERE should checkd here (we alredy have read tables)
    */
unknown's avatar
unknown committed
8979
    if (!join->conds || join->conds->val_int())
unknown's avatar
unknown committed
8980
    {
8981
      Next_select_func end_select= join->join_tab[join->tables-1].next_select;
8982 8983
      if (!(error=(*end_select)(join,join_tab,0)) || error == -3)
	error=(*end_select)(join,join_tab,1);
unknown's avatar
unknown committed
8984
    }
unknown's avatar
af  
unknown committed
8985 8986
    else if (join->send_row_on_empty_set())
      error= join->result->send_data(*join->fields);
unknown's avatar
unknown committed
8987 8988 8989
  }
  else
  {
unknown's avatar
unknown committed
8990
    error= sub_select(join,join_tab,0);
unknown's avatar
unknown committed
8991
    if (error >= 0)
unknown's avatar
unknown committed
8992
      error= sub_select(join,join_tab,1);
unknown's avatar
unknown committed
8993
    if (error == -3)
unknown's avatar
unknown committed
8994
      error= 0;					/* select_limit used */
unknown's avatar
unknown committed
8995
  }
8996

unknown's avatar
unknown committed
8997
  if (error >= 0)
unknown's avatar
unknown committed
8998
  {
8999 9000
    error=0;
    if (!table)					// If sending data to client
9001
    {
9002
      /*
9003 9004
	The following will unlock all cursors if the command wasn't an
	update command
9005
      */
9006
      join->join_free(0);				// Unlock all cursors
9007
      if (join->result->send_eof())
9008
	error= 1;				// Don't send error
9009
    }
unknown's avatar
unknown committed
9010 9011 9012 9013
    DBUG_PRINT("info",("%ld records output",join->send_records));
  }
  if (table)
  {
9014
    int tmp, new_errno= 0;
unknown's avatar
unknown committed
9015 9016
    if ((tmp=table->file->extra(HA_EXTRA_NO_CACHE)))
    {
9017
      DBUG_PRINT("error",("extra(HA_EXTRA_NO_CACHE) failed"));
9018
      new_errno= tmp;
unknown's avatar
unknown committed
9019
    }
unknown's avatar
unknown committed
9020
    if ((tmp=table->file->ha_index_or_rnd_end()))
unknown's avatar
unknown committed
9021
    {
unknown's avatar
unknown committed
9022
      DBUG_PRINT("error",("ha_index_or_rnd_end() failed"));
9023
      new_errno= tmp;
unknown's avatar
unknown committed
9024
    }
9025 9026
    if (new_errno)
      table->file->print_error(new_errno,MYF(0));
unknown's avatar
unknown committed
9027
  }
9028 9029 9030 9031 9032 9033
#ifndef DBUG_OFF
  if (error)
  {
    DBUG_PRINT("error",("Error: do_select() failed"));
  }
#endif
unknown's avatar
unknown committed
9034
  DBUG_RETURN(join->thd->net.report_error ? -1 : error);
unknown's avatar
unknown committed
9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048
}


static int
sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
{
  int error;

  if (end_of_records)
  {
    if ((error=flush_cached_records(join,join_tab,FALSE)) < 0)
      return error; /* purecov: inspected */
    return sub_select(join,join_tab,end_of_records);
  }
9049 9050
  if (join->thd->killed)		// If aborted by user
  {
unknown's avatar
SCRUM  
unknown committed
9051
    join->thd->send_kill_message();
9052 9053
    return -2;				 /* purecov: inspected */
  }
unknown's avatar
unknown committed
9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064
  if (join_tab->use_quick != 2 || test_if_quick_select(join_tab) <= 0)
  {
    if (!store_record_in_cache(&join_tab->cache))
      return 0;					// There is more room in cache
    return flush_cached_records(join,join_tab,FALSE);
  }
  if ((error=flush_cached_records(join,join_tab,TRUE)) < 0)
    return error; /* purecov: inspected */
  return sub_select(join,join_tab,end_of_records); /* Use ordinary select */
}

9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168
/*
  Retrieve records ends with a given beginning from the result of a join  

  SYNPOSIS
    sub_select()
    join      pointer to the structure providing all context info for the query
    join_tab  the first next table of the execution plan to be retrieved
    end_records  true when we need to perform final steps of retrival   

  DESCRIPTION
    For a given partial join record consisting of records from the tables 
    preceding the table join_tab in the execution plan, the function
    retrieves all matching full records from the result set and
    send them to the result set stream. 

  NOTES
    The function effectively implements the  final (n-k) nested loops
    of nested loops join algorithm, where k is the ordinal number of
    the join_tab table and n is the total number of tables in the join query.
    It performs nested loops joins with all conjunctive predicates from
    the where condition pushed as low to the tables as possible.
    E.g. for the query
      SELECT * FROM t1,t2,t3 
        WHERE t1.a=t2.a AND t2.b=t3.b AND t1.a BETWEEN 5 AND 9
    the predicate (t1.a BETWEEN 5 AND 9) will be pushed to table t1,
    given the selected plan prescribes to nest retrievals of the
    joined tables in the following order: t1,t2,t3.
    A pushed down predicate are attached to the table which it pushed to,
    at the field select_cond.
    When executing a nested loop of level k the function runs through
    the rows of 'join_tab' and for each row checks the pushed condition
    attached to the table.
    If it is false the function moves to the next row of the
    table. If the condition is true the function recursively executes (n-k-1)
    remaining embedded nested loops.
    The situation becomes more complicated if outer joins are involved in
    the execution plan. In this case the pushed down predicates can be
    checked only at certain conditions.
    Suppose for the query
      SELECT * FROM t1 LEFT JOIN (t2,t3) ON t3.a=t1.a 
        WHERE t1>2 AND (t2.b>5 OR t2.b IS NULL)
    the optimizer has chosen a plan with the table order t1,t2,t3.  
    The predicate P1=t1>2 will be pushed down to the table t1, while the
    predicate P2=(t2.b>5 OR t2.b IS NULL) will be attached to the table
    t2. But the second predicate can not be unconditionally tested right
    after a row from t2 has been read. This can be done only after the
    first row with t3.a=t1.a has been encountered.
    Thus, the second predicate P2 is supplied with a guarded value that are
    stored in the field 'found' of the first inner table for the outer join
    (table t2). When the first row with t3.a=t1.a for the  current row 
    of table t1  appears, the value becomes true. For now on the predicate
    is evaluated immediately after the row of table t2 has been read.
    When the first row with t3.a=t1.a has been encountered all
    conditions attached to the inner tables t2,t3 must be evaluated.
    Only when all of them are true the row is sent to the output stream.
    If not, the function returns to the lowest nest level that has a false
    attached condition.
    The predicates from on expressions are also pushed down. If in the 
    the above example the on expression were (t3.a=t1.a AND t2.a=t1.a),
    then t1.a=t2.a would be pushed down to table t2, and without any
    guard.
    If after the run through all rows of table t2, the first inner table
    for the outer join operation, it turns out that no matches are
    found for the current row of t1, then current row from table t1
    is complemented by nulls  for t2 and t3. Then the pushed down predicates
    are checked for the composed row almost in the same way as it had
    been done for the first row with a match. The only difference is
    the predicates  from on expressions are not checked. 

  IMPLEMENTATION
    The function forms output rows for a current partial join of k
    tables tables recursively.
    For each partial join record ending with a certain row from
    join_tab it calls sub_select that builds all possible matching
    tails from the result set.
    To be able  check predicates conditionally items of the class
    Item_func_trig_cond  are employed.
    An object of  this class is constructed from an item of class COND
    and a pointer to a guarding boolean variable.
    When the value of the guard variable is true the value of the object
    is the same as the value of the predicate, otherwise it's just returns
    true. 
    To carry out a return to a nested loop level of join table t the pointer 
    to t is remembered in the field 'return_tab' of the join structure.
    Consider the following query:
      SELECT * FROM t1,
                    LEFT JOIN
                    (t2, t3 LEFT JOIN (t4,t5) ON t5.a=t3.a)
                    ON t4.a=t2.a
         WHERE (t2.b=5 OR t2.b IS NULL) AND (t4.b=2 OR t4.b IS NULL)
    Suppose the chosen execution plan dictates the order t1,t2,t3,t4,t5
    and suppose for a given joined rows from tables t1,t2,t3 there are
    no rows in the result set yet.
    When first row from t5 that satisfies the on condition
    t5.a=t3.a is found, the pushed down predicate t4.b=2 OR t4.b IS NULL
    becomes 'activated', as well the predicate t4.a=t2.a. But
    the predicate (t2.b=5 OR t2.b IS NULL) can not be checked until
    t4.a=t2.a becomes true. 
    In order not to re-evaluate the predicates that were already evaluated
    as attached pushed down predicates, a pointer to the the first
    most inner unmatched table is maintained in join_tab->first_unmatched.
    Thus, when the first row from t5 with t5.a=t3.a is found
    this pointer for t5 is changed from t4 to t2.             

unknown's avatar
unknown committed
9169 9170 9171 9172
  STRUCTURE NOTES
    join_tab->first_unmatched points always backwards to the first inner
    table of the embedding nested join, if any.

9173 9174 9175 9176
  RETURN
    0, if success
    # of the error, otherwise
*/
unknown's avatar
unknown committed
9177 9178 9179 9180 9181 9182 9183 9184 9185

static int
sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
{
  join_tab->table->null_row=0;
  if (end_of_records)
    return (*join_tab->next_select)(join,join_tab+1,end_of_records);

  int error;
9186 9187 9188 9189
  JOIN_TAB *first_unmatched;
  JOIN_TAB *tab;
  /* Cache variables for faster loop */
  COND *select_cond= join_tab->select_cond;
9190
  my_bool *report_error= &(join->thd->net.report_error);
9191

unknown's avatar
unknown committed
9192
  join->return_tab= join_tab;
unknown's avatar
unknown committed
9193

9194
  if (join_tab->last_inner)
unknown's avatar
unknown committed
9195 9196
  {
    /* join_tab is the first inner table for an outer join operation. */
9197 9198 9199 9200 9201 9202 9203 9204 9205

    /* Set initial state of guard variables for this table.*/
    join_tab->found=0;
    join_tab->not_null_compl= 1;

    /* Set first_unmatched for the last inner table of this group */
    join_tab->last_inner->first_unmatched= join_tab; 
  }

unknown's avatar
unknown committed
9206 9207
  if (!(error=(*join_tab->read_first_record)(join_tab)))
  {
unknown's avatar
unknown committed
9208 9209 9210
    bool not_exists_optimize= join_tab->table->reginfo.not_exists_optimize;
    bool not_used_in_distinct=join_tab->not_used_in_distinct;
    ha_rows found_records=join->found_records;
unknown's avatar
unknown committed
9211 9212
    READ_RECORD *info= &join_tab->read_record;

9213
    join->thd->row_count= 0;
unknown's avatar
unknown committed
9214 9215 9216 9217
    do
    {
      if (join->thd->killed)			// Aborted by user
      {
unknown's avatar
SCRUM  
unknown committed
9218
	join->thd->send_kill_message();
unknown's avatar
unknown committed
9219 9220
	return -2;				/* purecov: inspected */
      }
9221
      DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
9222
      if (!select_cond || select_cond->val_int())
unknown's avatar
unknown committed
9223
      {
9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289
        /* 
          There is no select condition or the attached pushed down
          condition is true => a match is found.
	*/
        bool found= 1;
	while (join_tab->first_unmatched && found)
        {
          /*
             The while condition is always false if join_tab is not
             the last inner join table of an outer join operation. 
	  */ 
          first_unmatched= join_tab->first_unmatched;
          /*
             Mark that a match for current outer table is found.
             This activates push down conditional predicates attached
             to the all inner tables of the outer join.
	  */  
          first_unmatched->found= 1;
          for (tab= first_unmatched; tab <= join_tab; tab++)
          { 
            /* Check all predicates that has just been activated. */
            /*
              Actually all predicates non-guarded by first_unmatched->found
              will be re-evaluated again. It could be fixed, but, probably,
              it's not worth doing now.
	    */ 
            if (tab->select_cond && !tab->select_cond->val_int())
            {
              /* The condition attached to table tab is false */
              if (tab == join_tab)
                found= 0;
              else
              {
                /*
                  Set a return point if rejected predicate is attached 
                  not to the last table of the current nest level.
		*/
                join->return_tab= tab;
                return 0;
              }
            }
          }
          /* 
             Check whether join_tab is not the last inner table
             for another embedding outer join.
          */
          if ((first_unmatched= first_unmatched->first_upper) &&
              first_unmatched->last_inner != join_tab)
            first_unmatched= 0;
          join_tab->first_unmatched= first_unmatched;
        }
        
        /*
           It was not just a return to lower loop level when one
           of the newly activated predicates is evaluated as false 
           (See above join->return_tab= tab).
	*/             
        join->examined_rows++;
        join->thd->row_count++;
              
        if (found)
        {
          if (not_exists_optimize)
            break;
          /* A match from join_tab is found for the current partial join. */
	  if ((error=(*join_tab->next_select)(join, join_tab+1, 0)) < 0)
unknown's avatar
unknown committed
9290
	    return error;
unknown's avatar
unknown committed
9291
          if (join->return_tab < join_tab)
9292
              return 0;
unknown's avatar
unknown committed
9293 9294 9295 9296 9297
	  /*
	    Test if this was a SELECT DISTINCT query on a table that
	    was not in the field list;  In this case we can abort if
	    we found a row, as no new rows can be added to the result.
	  */
unknown's avatar
unknown committed
9298 9299
	  if (not_used_in_distinct && found_records != join->found_records)
	    return 0;
unknown's avatar
unknown committed
9300
	}
unknown's avatar
unknown committed
9301
	else
9302 9303 9304 9305 9306 9307 9308 9309 9310 9311
	  info->file->unlock_row();    
      }
      else
      {
        /* 
           The condition pushed down to the table join_tab rejects all rows 
           with the beginning coinciding with the current partial join.
	*/ 
        join->examined_rows++;
        join->thd->row_count++;
unknown's avatar
unknown committed
9312
      }
unknown's avatar
af  
unknown committed
9313

9314
    } while (!(error=info->read_record(info)) && !(*report_error));
unknown's avatar
unknown committed
9315
  }
9316
  if (error > 0 || (*report_error))				// Fatal error
unknown's avatar
unknown committed
9317 9318
    return -1;

9319 9320 9321 9322 9323 9324 9325 9326 9327 9328 9329 9330 9331
  if (join_tab->last_inner && !join_tab->found)
  {        
    /* 
      The table join_tab is the first inner table of a outer join operation
      and no matches has been found for the current outer row.
    */
    JOIN_TAB *last_inner_tab= join_tab->last_inner;
    for ( ; join_tab <= last_inner_tab ; join_tab++)
    { 
      /* Change the the values of guard predicate variables. */
      join_tab->found= 1;
      join_tab->not_null_compl= 0;
      /* The outer row is complemented by nulls for each inner tables */
9332
      restore_record(join_tab->table,s->default_values);  // Make empty record
9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359
      mark_as_null_row(join_tab->table);       // For group by without error
      select_cond= join_tab->select_cond;
      /* Check all attached conditions for inner table rows. */
      if (select_cond && !select_cond->val_int())
        return 0;
    }    
    join_tab--;
    /* 
       The row complemented by nulls might be the first row
       of embedding outer joins. 
       If so, perform the same actions as in the code 
       for the first regular outer join row above.
    */
    for ( ; ; )
    {
      first_unmatched= join_tab->first_unmatched;
      if ((first_unmatched= first_unmatched->first_upper) &&
          first_unmatched->last_inner != join_tab)
        first_unmatched= 0;
      join_tab->first_unmatched= first_unmatched;
      if (!first_unmatched)
        break;
      first_unmatched->found= 1;
      for (JOIN_TAB *tab= first_unmatched; tab <= join_tab; tab++)
      {  
        if (tab->select_cond && !tab->select_cond->val_int())
        {
unknown's avatar
unknown committed
9360
	  join->return_tab= tab;
9361 9362 9363
          return 0;
        }
      }
unknown's avatar
unknown committed
9364
    }
9365 9366 9367 9368 9369 9370 9371 9372
    /*
      The row complemented by nulls satisfies all conditions
      attached to inner tables.
      Send the row complemented by nulls to be joined with the 
      remaining tables.
    */     
    if ((error=(*join_tab->next_select)(join, join_tab+1 ,0)) < 0)
      return error;
unknown's avatar
unknown committed
9373 9374 9375 9376 9377 9378
  }
  return 0;
}


static int
unknown's avatar
af  
unknown committed
9379
flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
unknown's avatar
unknown committed
9380 9381 9382 9383 9384 9385
{
  int error;
  READ_RECORD *info;

  if (!join_tab->cache.records)
    return 0;				/* Nothing to do */
unknown's avatar
af  
unknown committed
9386
  if (skip_last)
unknown's avatar
unknown committed
9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398
    (void) store_record_in_cache(&join_tab->cache); // Must save this for later
  if (join_tab->use_quick == 2)
  {
    if (join_tab->select->quick)
    {					/* Used quick select last. reset it */
      delete join_tab->select->quick;
      join_tab->select->quick=0;
    }
  }
 /* read through all records */
  if ((error=join_init_read_record(join_tab)))
  {
9399
    reset_cache_write(&join_tab->cache);
unknown's avatar
unknown committed
9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413
    return -error;			/* No records or error */
  }

  for (JOIN_TAB *tmp=join->join_tab; tmp != join_tab ; tmp++)
  {
    tmp->status=tmp->table->status;
    tmp->table->status=0;
  }

  info= &join_tab->read_record;
  do
  {
    if (join->thd->killed)
    {
unknown's avatar
SCRUM  
unknown committed
9414
      join->thd->send_kill_message();
unknown's avatar
unknown committed
9415 9416 9417 9418
      return -2;				// Aborted by user /* purecov: inspected */
    }
    SQL_SELECT *select=join_tab->select;
    if (!error && (!join_tab->cache.select ||
unknown's avatar
af  
unknown committed
9419
		   !join_tab->cache.select->skip_record()))
unknown's avatar
unknown committed
9420 9421
    {
      uint i;
9422
      reset_cache_read(&join_tab->cache);
unknown's avatar
af  
unknown committed
9423
      for (i=(join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;)
unknown's avatar
unknown committed
9424 9425
      {
	read_cached_record(join_tab);
unknown's avatar
af  
unknown committed
9426
	if (!select || !select->skip_record())
unknown's avatar
unknown committed
9427
	  if ((error=(join_tab->next_select)(join,join_tab+1,0)) < 0)
9428 9429
          {
            reset_cache_write(&join_tab->cache);
unknown's avatar
unknown committed
9430
	    return error; /* purecov: inspected */
9431
          }
unknown's avatar
unknown committed
9432 9433 9434 9435
      }
    }
  } while (!(error=info->read_record(info)));

unknown's avatar
af  
unknown committed
9436
  if (skip_last)
unknown's avatar
unknown committed
9437
    read_cached_record(join_tab);		// Restore current record
9438
  reset_cache_write(&join_tab->cache);
unknown's avatar
unknown committed
9439 9440 9441 9442 9443 9444 9445 9446 9447
  if (error > 0)				// Fatal error
    return -1;					/* purecov: inspected */
  for (JOIN_TAB *tmp2=join->join_tab; tmp2 != join_tab ; tmp2++)
    tmp2->table->status=tmp2->status;
  return 0;
}


/*****************************************************************************
9448 9449
  The different ways to read a record
  Returns -1 if row was not found, 0 if row was found and 1 on errors
unknown's avatar
unknown committed
9450
*****************************************************************************/
9451 9452 9453

/* Help function when we get some an error from the table handler */

9454
int report_error(TABLE *table, int error)
9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466
{
  if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND)
  {
    table->status= STATUS_GARBAGE;
    return -1;					// key not found; ok
  }
  /*
    Locking reads can legally return also these errors, do not
    print them to the .err log
  */
  if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
    sql_print_error("Got error %d when reading table '%s'",
9467
		    error, table->s->path);
9468 9469 9470 9471 9472
  table->file->print_error(error,MYF(0));
  return 1;
}


9473
int safe_index_read(JOIN_TAB *tab)
9474 9475 9476 9477 9478 9479 9480 9481 9482 9483 9484
{
  int error;
  TABLE *table= tab->table;
  if ((error=table->file->index_read(table->record[0],
				     tab->ref.key_buff,
				     tab->ref.key_length, HA_READ_KEY_EXACT)))
    return report_error(table, error);
  return 0;
}


unknown's avatar
unknown committed
9485
static int
9486
join_read_const_table(JOIN_TAB *tab, POSITION *pos)
unknown's avatar
unknown committed
9487 9488
{
  int error;
9489 9490 9491 9492 9493 9494 9495
  DBUG_ENTER("join_read_const_table");
  TABLE *table=tab->table;
  table->const_table=1;
  table->null_row=0;
  table->status=STATUS_NO_RECORD;
  
  if (tab->type == JT_SYSTEM)
unknown's avatar
unknown committed
9496
  {
9497 9498 9499 9500 9501
    if ((error=join_read_system(tab)))
    {						// Info for DESCRIBE
      tab->info="const row not found";
      /* Mark for EXPLAIN that the row was not found */
      pos->records_read=0.0;
9502
      if (!table->maybe_null || error > 0)
9503
	DBUG_RETURN(error);
unknown's avatar
unknown committed
9504
    }
9505 9506 9507
  }
  else
  {
unknown's avatar
af  
unknown committed
9508
    if (!table->key_read && table->used_keys.is_set(tab->ref.key) &&
9509 9510
	!table->no_keyread &&
        (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY)
unknown's avatar
af  
unknown committed
9511 9512 9513
    {
      table->key_read=1;
      table->file->extra(HA_EXTRA_KEYREAD);
unknown's avatar
unknown committed
9514
      tab->index= tab->ref.key;
unknown's avatar
af  
unknown committed
9515
    }
9516
    if ((error=join_read_const(tab)))
unknown's avatar
unknown committed
9517
    {
9518 9519 9520
      tab->info="unique row not found";
      /* Mark for EXPLAIN that the row was not found */
      pos->records_read=0.0;
9521
      if (!table->maybe_null || error > 0)
9522
	DBUG_RETURN(error);
unknown's avatar
unknown committed
9523
    }
unknown's avatar
unknown committed
9524 9525 9526 9527 9528
    if (table->key_read)
    {
      table->key_read=0;
      table->file->extra(HA_EXTRA_NO_KEYREAD);
    }
unknown's avatar
unknown committed
9529
  }
unknown's avatar
unknown committed
9530
  if (*tab->on_expr_ref && !table->null_row)
9531
  {
unknown's avatar
unknown committed
9532
    if ((table->null_row= test((*tab->on_expr_ref)->val_int() == 0)))
unknown's avatar
af  
unknown committed
9533 9534
      mark_as_null_row(table);  
  }
9535 9536
  if (!table->null_row)
    table->maybe_null=0;
unknown's avatar
unknown committed
9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547
  DBUG_RETURN(0);
}


static int
join_read_system(JOIN_TAB *tab)
{
  TABLE *table= tab->table;
  int error;
  if (table->status & STATUS_GARBAGE)		// If first read
  {
9548
    if ((error=table->file->read_first_row(table->record[0],
9549
					   table->s->primary_key)))
unknown's avatar
unknown committed
9550 9551
    {
      if (error != HA_ERR_END_OF_FILE)
9552
	return report_error(table, error);
unknown's avatar
unknown committed
9553
      mark_as_null_row(tab->table);
unknown's avatar
unknown committed
9554 9555 9556
      empty_record(table);			// Make empty record
      return -1;
    }
unknown's avatar
unknown committed
9557
    store_record(table,record[1]);
unknown's avatar
unknown committed
9558 9559
  }
  else if (!table->status)			// Only happens with left join
unknown's avatar
unknown committed
9560
    restore_record(table,record[1]);			// restore old record
unknown's avatar
unknown committed
9561 9562 9563 9564 9565
  table->null_row=0;
  return table->status ? -1 : 0;
}


9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578
/*
  Read a table when there is at most one matching row

  SYNOPSIS
    join_read_const()
    tab			Table to read

  RETURN
    0	Row was found
    -1  Row was not found
   1    Got an error (other than row not found) during read
*/

unknown's avatar
unknown committed
9579 9580 9581 9582 9583 9584 9585
static int
join_read_const(JOIN_TAB *tab)
{
  int error;
  TABLE *table= tab->table;
  if (table->status & STATUS_GARBAGE)		// If first read
  {
9586
    table->status= 0;
unknown's avatar
unknown committed
9587
    if (cp_buffer_from_ref(tab->join->thd, &tab->ref))
unknown's avatar
unknown committed
9588 9589 9590 9591 9592 9593 9594 9595 9596
      error=HA_ERR_KEY_NOT_FOUND;
    else
    {
      error=table->file->index_read_idx(table->record[0],tab->ref.key,
					(byte*) tab->ref.key_buff,
					tab->ref.key_length,HA_READ_KEY_EXACT);
    }
    if (error)
    {
9597
      table->status= STATUS_NOT_FOUND;
unknown's avatar
unknown committed
9598
      mark_as_null_row(tab->table);
unknown's avatar
unknown committed
9599 9600
      empty_record(table);
      if (error != HA_ERR_KEY_NOT_FOUND)
9601
	return report_error(table, error);
unknown's avatar
unknown committed
9602 9603
      return -1;
    }
unknown's avatar
unknown committed
9604
    store_record(table,record[1]);
unknown's avatar
unknown committed
9605
  }
unknown's avatar
unknown committed
9606 9607 9608
  else if (!(table->status & ~STATUS_NULL_ROW))	// Only happens with left join
  {
    table->status=0;
unknown's avatar
unknown committed
9609
    restore_record(table,record[1]);			// restore old record
unknown's avatar
unknown committed
9610
  }
unknown's avatar
unknown committed
9611 9612 9613 9614 9615 9616 9617 9618 9619 9620 9621
  table->null_row=0;
  return table->status ? -1 : 0;
}


static int
join_read_key(JOIN_TAB *tab)
{
  int error;
  TABLE *table= tab->table;

unknown's avatar
unknown committed
9622 9623
  if (!table->file->inited)
    table->file->ha_index_init(tab->ref.key);
unknown's avatar
unknown committed
9624
  if (cmp_buffer_with_ref(tab) ||
9625
      (table->status & (STATUS_GARBAGE | STATUS_NO_PARENT | STATUS_NULL_ROW)))
unknown's avatar
unknown committed
9626 9627 9628 9629 9630 9631 9632 9633 9634 9635
  {
    if (tab->ref.key_err)
    {
      table->status=STATUS_NOT_FOUND;
      return -1;
    }
    error=table->file->index_read(table->record[0],
				  tab->ref.key_buff,
				  tab->ref.key_length,HA_READ_KEY_EXACT);
    if (error && error != HA_ERR_KEY_NOT_FOUND)
9636
      return report_error(table, error);
unknown's avatar
unknown committed
9637
  }
9638
  table->null_row=0;
unknown's avatar
unknown committed
9639 9640 9641 9642 9643 9644 9645 9646 9647 9648
  return table->status ? -1 : 0;
}


static int
join_read_always_key(JOIN_TAB *tab)
{
  int error;
  TABLE *table= tab->table;

unknown's avatar
unknown committed
9649 9650
  if (!table->file->inited)
    table->file->ha_index_init(tab->ref.key);
unknown's avatar
unknown committed
9651
  if (cp_buffer_from_ref(tab->join->thd, &tab->ref))
unknown's avatar
unknown committed
9652 9653 9654 9655 9656 9657
    return -1;
  if ((error=table->file->index_read(table->record[0],
				     tab->ref.key_buff,
				     tab->ref.key_length,HA_READ_KEY_EXACT)))
  {
    if (error != HA_ERR_KEY_NOT_FOUND)
9658
      return report_error(table, error);
unknown's avatar
unknown committed
9659 9660 9661 9662 9663
    return -1; /* purecov: inspected */
  }
  return 0;
}

9664

9665 9666 9667 9668 9669 9670 9671 9672 9673 9674 9675
/*
  This function is used when optimizing away ORDER BY in 
  SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
*/
  
static int
join_read_last_key(JOIN_TAB *tab)
{
  int error;
  TABLE *table= tab->table;

unknown's avatar
unknown committed
9676 9677
  if (!table->file->inited)
    table->file->ha_index_init(tab->ref.key);
unknown's avatar
unknown committed
9678
  if (cp_buffer_from_ref(tab->join->thd, &tab->ref))
9679 9680 9681 9682 9683 9684
    return -1;
  if ((error=table->file->index_read_last(table->record[0],
					  tab->ref.key_buff,
					  tab->ref.key_length)))
  {
    if (error != HA_ERR_KEY_NOT_FOUND)
9685
      return report_error(table, error);
9686 9687 9688 9689 9690
    return -1; /* purecov: inspected */
  }
  return 0;
}

unknown's avatar
unknown committed
9691 9692 9693 9694 9695 9696 9697 9698 9699 9700

	/* ARGSUSED */
static int
join_no_more_records(READ_RECORD *info __attribute__((unused)))
{
  return -1;
}


static int
9701
join_read_next_same(READ_RECORD *info)
unknown's avatar
unknown committed
9702 9703 9704 9705 9706 9707 9708 9709 9710 9711
{
  int error;
  TABLE *table= info->table;
  JOIN_TAB *tab=table->reginfo.join_tab;

  if ((error=table->file->index_next_same(table->record[0],
					  tab->ref.key_buff,
					  tab->ref.key_length)))
  {
    if (error != HA_ERR_END_OF_FILE)
9712
      return report_error(table, error);
unknown's avatar
unknown committed
9713 9714 9715 9716 9717 9718
    table->status= STATUS_GARBAGE;
    return -1;
  }
  return 0;
}

9719

9720 9721 9722 9723 9724 9725 9726 9727
static int
join_read_prev_same(READ_RECORD *info)
{
  int error;
  TABLE *table= info->table;
  JOIN_TAB *tab=table->reginfo.join_tab;

  if ((error=table->file->index_prev(table->record[0])))
9728
    return report_error(table, error);
unknown's avatar
af  
unknown committed
9729 9730
  if (key_cmp_if_same(table, tab->ref.key_buff, tab->ref.key,
                      tab->ref.key_length))
9731 9732
  {
    table->status=STATUS_NOT_FOUND;
9733
    error= -1;
9734 9735 9736 9737
  }
  return error;
}

unknown's avatar
unknown committed
9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752

static int
join_init_quick_read_record(JOIN_TAB *tab)
{
  if (test_if_quick_select(tab) == -1)
    return -1;					/* No possible records */
  return join_init_read_record(tab);
}


static int
test_if_quick_select(JOIN_TAB *tab)
{
  delete tab->select->quick;
  tab->select->quick=0;
9753 9754
  return tab->select->test_quick_select(tab->join->thd, tab->keys,
					(table_map) 0, HA_POS_ERROR);
unknown's avatar
unknown committed
9755 9756 9757 9758 9759 9760
}


static int
join_init_read_record(JOIN_TAB *tab)
{
9761 9762
  if (tab->select && tab->select->quick && tab->select->quick->reset())
    return 1;
9763 9764
  init_read_record(&tab->read_record, tab->join->thd, tab->table,
		   tab->select,1,1);
unknown's avatar
unknown committed
9765 9766 9767
  return (*tab->read_record.read_record)(&tab->read_record);
}

9768

unknown's avatar
unknown committed
9769
static int
9770
join_read_first(JOIN_TAB *tab)
unknown's avatar
unknown committed
9771 9772 9773
{
  int error;
  TABLE *table=tab->table;
9774
  if (!table->key_read && table->used_keys.is_set(tab->index) &&
unknown's avatar
unknown committed
9775
      !table->no_keyread)
unknown's avatar
unknown committed
9776 9777 9778 9779 9780
  {
    table->key_read=1;
    table->file->extra(HA_EXTRA_KEYREAD);
  }
  tab->table->status=0;
9781
  tab->read_record.read_record=join_read_next;
unknown's avatar
unknown committed
9782 9783 9784 9785
  tab->read_record.table=table;
  tab->read_record.file=table->file;
  tab->read_record.index=tab->index;
  tab->read_record.record=table->record[0];
unknown's avatar
unknown committed
9786 9787
  if (!table->file->inited)
    table->file->ha_index_init(tab->index);
9788
  if ((error=tab->table->file->index_first(tab->table->record[0])))
unknown's avatar
unknown committed
9789 9790
  {
    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
9791
      report_error(table, error);
unknown's avatar
unknown committed
9792 9793 9794 9795 9796
    return -1;
  }
  return 0;
}

9797

unknown's avatar
unknown committed
9798
static int
9799
join_read_next(READ_RECORD *info)
unknown's avatar
unknown committed
9800
{
9801 9802 9803
  int error;
  if ((error=info->file->index_next(info->record)))
    return report_error(info->table, error);
unknown's avatar
unknown committed
9804 9805 9806
  return 0;
}

9807

unknown's avatar
unknown committed
9808
static int
9809
join_read_last(JOIN_TAB *tab)
unknown's avatar
unknown committed
9810 9811 9812
{
  TABLE *table=tab->table;
  int error;
9813
  if (!table->key_read && table->used_keys.is_set(tab->index) &&
9814
      !table->no_keyread)
unknown's avatar
unknown committed
9815 9816 9817 9818 9819
  {
    table->key_read=1;
    table->file->extra(HA_EXTRA_KEYREAD);
  }
  tab->table->status=0;
9820
  tab->read_record.read_record=join_read_prev;
unknown's avatar
unknown committed
9821 9822 9823 9824
  tab->read_record.table=table;
  tab->read_record.file=table->file;
  tab->read_record.index=tab->index;
  tab->read_record.record=table->record[0];
unknown's avatar
unknown committed
9825 9826
  if (!table->file->inited)
    table->file->ha_index_init(tab->index);
9827 9828
  if ((error= tab->table->file->index_last(tab->table->record[0])))
    return report_error(table, error);
unknown's avatar
unknown committed
9829 9830 9831
  return 0;
}

9832

unknown's avatar
unknown committed
9833
static int
9834
join_read_prev(READ_RECORD *info)
unknown's avatar
unknown committed
9835
{
9836 9837 9838
  int error;
  if ((error= info->file->index_prev(info->record)))
    return report_error(info->table, error);
unknown's avatar
unknown committed
9839 9840 9841
  return 0;
}

9842

unknown's avatar
unknown committed
9843 9844 9845 9846 9847 9848
static int
join_ft_read_first(JOIN_TAB *tab)
{
  int error;
  TABLE *table= tab->table;

unknown's avatar
unknown committed
9849 9850
  if (!table->file->inited)
    table->file->ha_index_init(tab->ref.key);
unknown's avatar
unknown committed
9851
#if NOT_USED_YET
unknown's avatar
unknown committed
9852
  if (cp_buffer_from_ref(tab->join->thd, &tab->ref)) // as ft-key doesn't use store_key's
unknown's avatar
unknown committed
9853
    return -1;                             // see also FT_SELECT::init()
unknown's avatar
unknown committed
9854
#endif
9855
  table->file->ft_init();
unknown's avatar
unknown committed
9856

9857 9858
  if ((error= table->file->ft_read(table->record[0])))
    return report_error(table, error);
unknown's avatar
unknown committed
9859 9860 9861 9862 9863 9864
  return 0;
}

static int
join_ft_read_next(READ_RECORD *info)
{
9865 9866 9867
  int error;
  if ((error= info->file->ft_read(info->table->record[0])))
    return report_error(info->table, error);
unknown's avatar
unknown committed
9868 9869 9870 9871
  return 0;
}


9872 9873 9874 9875 9876 9877 9878 9879 9880 9881
/*
  Reading of key with key reference and one part that may be NULL
*/

static int
join_read_always_key_or_null(JOIN_TAB *tab)
{
  int res;

  /* First read according to key which is NOT NULL */
unknown's avatar
af  
unknown committed
9882
  *tab->ref.null_ref_key= 0;			// Clear null byte
9883 9884 9885 9886
  if ((res= join_read_always_key(tab)) >= 0)
    return res;

  /* Then read key with null value */
unknown's avatar
af  
unknown committed
9887
  *tab->ref.null_ref_key= 1;			// Set null byte
9888 9889 9890 9891 9892 9893 9894 9895 9896 9897 9898 9899 9900
  return safe_index_read(tab);
}


static int
join_read_next_same_or_null(READ_RECORD *info)
{
  int error;
  if ((error= join_read_next_same(info)) >= 0)
    return error;
  JOIN_TAB *tab= info->table->reginfo.join_tab;

  /* Test if we have already done a read after null key */
unknown's avatar
af  
unknown committed
9901
  if (*tab->ref.null_ref_key)
9902
    return -1;					// All keys read
unknown's avatar
af  
unknown committed
9903 9904
  *tab->ref.null_ref_key= 1;			// Set null byte
  return safe_index_read(tab);			// then read null keys
9905 9906 9907
}


unknown's avatar
unknown committed
9908
/*****************************************************************************
9909 9910 9911
  The different end of select functions
  These functions returns < 0 when end is reached, 0 on ok and > 0 if a
  fatal error (like table corruption) was detected
unknown's avatar
unknown committed
9912 9913
*****************************************************************************/

9914
/* ARGSUSED */
unknown's avatar
unknown committed
9915 9916 9917 9918 9919 9920 9921 9922
static int
end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
	 bool end_of_records)
{
  DBUG_ENTER("end_send");
  if (!end_of_records)
  {
    int error;
9923
    if (join->having && join->having->val_int() == 0)
unknown's avatar
unknown committed
9924
      DBUG_RETURN(0);				// Didn't match having
9925
    error=0;
unknown's avatar
unknown committed
9926 9927
    if (join->procedure)
      error=join->procedure->send_row(*join->fields);
unknown's avatar
unknown committed
9928
    else if (join->do_send_rows)
unknown's avatar
unknown committed
9929 9930 9931
      error=join->result->send_data(*join->fields);
    if (error)
      DBUG_RETURN(-1); /* purecov: inspected */
9932
    if (++join->send_records >= join->unit->select_limit_cnt &&
unknown's avatar
unknown committed
9933
	join->do_send_rows)
9934 9935 9936
    {
      if (join->select_options & OPTION_FOUND_ROWS)
      {
9937
	JOIN_TAB *jt=join->join_tab;
9938
	if ((join->tables == 1) && !join->tmp_table && !join->sort_and_group
9939
	    && !join->send_group_parts && !join->having && !jt->select_cond &&
9940
	    !(jt->select && jt->select->quick) &&
unknown's avatar
unknown committed
9941 9942
	    !(jt->table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
            (jt->ref.key < 0))
9943
	{
9944
	  /* Join over all rows in table;  Return number of found rows */
9945 9946
	  TABLE *table=jt->table;

9947
	  join->select_options ^= OPTION_FOUND_ROWS;
unknown's avatar
unknown committed
9948 9949
	  if (table->sort.record_pointers ||
	      (table->sort.io_cache && my_b_inited(table->sort.io_cache)))
9950 9951
	  {
	    /* Using filesort */
unknown's avatar
unknown committed
9952
	    join->send_records= table->sort.found_records;
9953 9954 9955 9956 9957 9958
	  }
	  else
	  {
	    table->file->info(HA_STATUS_VARIABLE);
	    join->send_records = table->file->records;
	  }
9959 9960 9961
	}
	else 
	{
9962
	  join->do_send_rows= 0;
unknown's avatar
unknown committed
9963 9964
	  if (join->unit->fake_select_lex)
	    join->unit->fake_select_lex->select_limit= HA_POS_ERROR;
9965 9966
	  DBUG_RETURN(0);
	}
9967
      }
unknown's avatar
unknown committed
9968
      DBUG_RETURN(-3);				// Abort nicely
9969
    }
9970 9971 9972 9973 9974 9975 9976 9977
    else if (join->send_records >= join->fetch_limit)
    {
      /*
        There is a server side cursor and all rows for
        this fetch request are sent.
      */
      DBUG_RETURN(-4);
    }
unknown's avatar
unknown committed
9978 9979 9980 9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002 10003 10004
  }
  else
  {
    if (join->procedure && join->procedure->end_of_records())
      DBUG_RETURN(-1);
  }
  DBUG_RETURN(0);
}


	/* ARGSUSED */
static int
end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
	       bool end_of_records)
{
  int idx= -1;
  DBUG_ENTER("end_send_group");

  if (!join->first_record || end_of_records ||
      (idx=test_if_group_changed(join->group_fields)) >= 0)
  {
    if (join->first_record || (end_of_records && !join->group))
    {
      if (join->procedure)
	join->procedure->end_group();
      if (idx < (int) join->send_group_parts)
      {
10005
	int error=0;
unknown's avatar
unknown committed
10006 10007
	if (join->procedure)
	{
10008
	  if (join->having && join->having->val_int() == 0)
unknown's avatar
unknown committed
10009
	    error= -1;				// Didn't satisfy having
10010 10011 10012 10013 10014 10015
 	  else
	  {
	    if (join->do_send_rows)
	      error=join->procedure->send_row(*join->fields) ? 1 : 0;
	    join->send_records++;
	  }
unknown's avatar
unknown committed
10016 10017 10018 10019 10020 10021
	  if (end_of_records && join->procedure->end_of_records())
	    error= 1;				// Fatal error
	}
	else
	{
	  if (!join->first_record)
10022 10023
	  {
	    /* No matching rows for group function */
10024
	    join->clear();
10025
	  }
10026
	  if (join->having && join->having->val_int() == 0)
unknown's avatar
unknown committed
10027
	    error= -1;				// Didn't satisfy having
10028 10029 10030 10031 10032 10033 10034 10035 10036 10037 10038
	  else
	  {
	    if (join->do_send_rows)
	      error=join->result->send_data(*join->fields) ? 1 : 0;
	    join->send_records++;
	  }
	  if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0)
	  {
	    if (join->rollup_send_data((uint) (idx+1)))
	      error= 1;
	  }
unknown's avatar
unknown committed
10039 10040 10041
	}
	if (error > 0)
	  DBUG_RETURN(-1);			/* purecov: inspected */
10042 10043
	if (end_of_records)
	  DBUG_RETURN(0);
10044
	if (join->send_records >= join->unit->select_limit_cnt &&
10045 10046 10047 10048 10049
	    join->do_send_rows)
	{
	  if (!(join->select_options & OPTION_FOUND_ROWS))
	    DBUG_RETURN(-3);				// Abort nicely
	  join->do_send_rows=0;
10050
	  join->unit->select_limit_cnt = HA_POS_ERROR;
10051
        }
10052 10053 10054 10055 10056 10057 10058 10059
        else if (join->send_records >= join->fetch_limit)
        {
          /*
            There is a server side cursor and all rows
            for this fetch request are sent.
          */
          DBUG_RETURN(-4);
        }
unknown's avatar
unknown committed
10060 10061 10062 10063 10064 10065 10066 10067 10068 10069 10070 10071
      }
    }
    else
    {
      if (end_of_records)
	DBUG_RETURN(0);
      join->first_record=1;
      VOID(test_if_group_changed(join->group_fields));
    }
    if (idx < (int) join->send_group_parts)
    {
      copy_fields(&join->tmp_table_param);
10072 10073
      if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
	DBUG_RETURN(-1);
unknown's avatar
unknown committed
10074 10075 10076 10077 10078 10079 10080 10081 10082 10083 10084 10085 10086 10087 10088 10089 10090 10091 10092 10093 10094 10095 10096 10097
      if (join->procedure)
	join->procedure->add();
      DBUG_RETURN(0);
    }
  }
  if (update_sum_func(join->sum_funcs))
    DBUG_RETURN(-1);
  if (join->procedure)
    join->procedure->add();
  DBUG_RETURN(0);
}


	/* ARGSUSED */
static int
end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
	  bool end_of_records)
{
  TABLE *table=join->tmp_table;
  int error;
  DBUG_ENTER("end_write");

  if (join->thd->killed)			// Aborted by user
  {
unknown's avatar
SCRUM  
unknown committed
10098
    join->thd->send_kill_message();
unknown's avatar
unknown committed
10099 10100 10101 10102 10103
    DBUG_RETURN(-2);				/* purecov: inspected */
  }
  if (!end_of_records)
  {
    copy_fields(&join->tmp_table_param);
unknown's avatar
unknown committed
10104
    copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
10105

10106
#ifdef TO_BE_DELETED
unknown's avatar
unknown committed
10107 10108 10109 10110 10111 10112 10113 10114 10115
    if (!table->uniques)			// If not unique handling
    {
      /* Copy null values from group to row */
      ORDER   *group;
      for (group=table->group ; group ; group=group->next)
      {
	Item *item= *group->item;
	if (item->maybe_null)
	{
10116
	  Field *field=item->get_tmp_table_field();
10117
	  field->ptr[-1]= (byte) (field->is_null() ? 1 : 0);
unknown's avatar
unknown committed
10118 10119 10120
	}
      }
    }
10121
#endif
unknown's avatar
unknown committed
10122 10123
    if (!join->having || join->having->val_int())
    {
unknown's avatar
unknown committed
10124
      join->found_records++;
unknown's avatar
unknown committed
10125 10126
      if ((error=table->file->write_row(table->record[0])))
      {
unknown's avatar
unknown committed
10127 10128 10129
	if (error == HA_ERR_FOUND_DUPP_KEY ||
	    error == HA_ERR_FOUND_DUPP_UNIQUE)
	  goto end;
unknown's avatar
unknown committed
10130 10131
	if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
				    error,1))
10132
	  DBUG_RETURN(-1);			// Not a table_is_full error
10133
	table->s->uniques=0;			// To ensure rows are the same
10134
      }
unknown's avatar
unknown committed
10135
      if (++join->send_records >= join->tmp_table_param.end_write_records &&
10136 10137 10138 10139 10140
	  join->do_send_rows)
      {
	if (!(join->select_options & OPTION_FOUND_ROWS))
	  DBUG_RETURN(-3);
	join->do_send_rows=0;
10141
	join->unit->select_limit_cnt = HA_POS_ERROR;
10142
	DBUG_RETURN(0);
unknown's avatar
unknown committed
10143 10144 10145
      }
    }
  }
unknown's avatar
unknown committed
10146
end:
unknown's avatar
unknown committed
10147 10148 10149 10150 10151 10152 10153 10154 10155 10156 10157 10158 10159 10160 10161 10162 10163 10164 10165
  DBUG_RETURN(0);
}

/* Group by searching after group record and updating it if possible */
/* ARGSUSED */

static int
end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
	   bool end_of_records)
{
  TABLE *table=join->tmp_table;
  ORDER   *group;
  int	  error;
  DBUG_ENTER("end_update");

  if (end_of_records)
    DBUG_RETURN(0);
  if (join->thd->killed)			// Aborted by user
  {
unknown's avatar
SCRUM  
unknown committed
10166
    join->thd->send_kill_message();
unknown's avatar
unknown committed
10167 10168 10169
    DBUG_RETURN(-2);				/* purecov: inspected */
  }

unknown's avatar
unknown committed
10170
  join->found_records++;
unknown's avatar
unknown committed
10171 10172 10173 10174 10175 10176
  copy_fields(&join->tmp_table_param);		// Groups are copied twice.
  /* Make a key of group index */
  for (group=table->group ; group ; group=group->next)
  {
    Item *item= *group->item;
    item->save_org_in_field(group->field);
10177
    /* Store in the used key if the field was 0 */
unknown's avatar
unknown committed
10178
    if (item->maybe_null)
10179
      group->buff[-1]=item->null_value ? 1 : 0;
unknown's avatar
unknown committed
10180 10181 10182 10183 10184
  }
  if (!table->file->index_read(table->record[1],
			       join->tmp_table_param.group_buff,0,
			       HA_READ_KEY_EXACT))
  {						/* Update old record */
unknown's avatar
unknown committed
10185
    restore_record(table,record[1]);
unknown's avatar
unknown committed
10186 10187 10188 10189 10190 10191 10192 10193 10194 10195
    update_tmptable_sum_func(join->sum_funcs,table);
    if ((error=table->file->update_row(table->record[1],
				       table->record[0])))
    {
      table->file->print_error(error,MYF(0));	/* purecov: inspected */
      DBUG_RETURN(-1);				/* purecov: inspected */
    }
    DBUG_RETURN(0);
  }

10196 10197 10198 10199 10200
  /*
    Copy null bits from group key to table
    We can't copy all data as the key may have different format
    as the row data (for example as with VARCHAR keys)
  */
unknown's avatar
unknown committed
10201 10202 10203 10204
  KEY_PART_INFO *key_part;
  for (group=table->group,key_part=table->key_info[0].key_part;
       group ;
       group=group->next,key_part++)
10205 10206 10207 10208
  {
    if (key_part->null_bit)
      memcpy(table->record[0]+key_part->offset, group->buff, 1);
  }
unknown's avatar
unknown committed
10209
  init_tmptable_sum_functions(join->sum_funcs);
unknown's avatar
unknown committed
10210
  copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
10211 10212
  if ((error=table->file->write_row(table->record[0])))
  {
unknown's avatar
unknown committed
10213 10214
    if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
				error, 0))
unknown's avatar
unknown committed
10215 10216
      DBUG_RETURN(-1);				// Not a table_is_full error
    /* Change method to update rows */
unknown's avatar
unknown committed
10217
    table->file->ha_index_init(0);
unknown's avatar
unknown committed
10218 10219 10220 10221 10222 10223
    join->join_tab[join->tables-1].next_select=end_unique_update;
  }
  join->send_records++;
  DBUG_RETURN(0);
}

10224

unknown's avatar
unknown committed
10225 10226 10227 10228 10229 10230 10231 10232 10233 10234 10235 10236 10237 10238
/* Like end_update, but this is done with unique constraints instead of keys */

static int
end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
		  bool end_of_records)
{
  TABLE *table=join->tmp_table;
  int	  error;
  DBUG_ENTER("end_unique_update");

  if (end_of_records)
    DBUG_RETURN(0);
  if (join->thd->killed)			// Aborted by user
  {
unknown's avatar
SCRUM  
unknown committed
10239
    join->thd->send_kill_message();
unknown's avatar
unknown committed
10240 10241 10242 10243 10244
    DBUG_RETURN(-2);				/* purecov: inspected */
  }

  init_tmptable_sum_functions(join->sum_funcs);
  copy_fields(&join->tmp_table_param);		// Groups are copied twice.
unknown's avatar
unknown committed
10245
  copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
10246 10247 10248 10249 10250 10251 10252 10253 10254 10255 10256 10257 10258 10259 10260

  if (!(error=table->file->write_row(table->record[0])))
    join->send_records++;			// New group
  else
  {
    if ((int) table->file->get_dup_key(error) < 0)
    {
      table->file->print_error(error,MYF(0));	/* purecov: inspected */
      DBUG_RETURN(-1);				/* purecov: inspected */
    }
    if (table->file->rnd_pos(table->record[1],table->file->dupp_ref))
    {
      table->file->print_error(error,MYF(0));	/* purecov: inspected */
      DBUG_RETURN(-1);				/* purecov: inspected */
    }
unknown's avatar
unknown committed
10261
    restore_record(table,record[1]);
unknown's avatar
unknown committed
10262 10263 10264 10265 10266 10267 10268 10269 10270 10271 10272 10273 10274 10275 10276 10277 10278 10279 10280 10281 10282 10283 10284 10285
    update_tmptable_sum_func(join->sum_funcs,table);
    if ((error=table->file->update_row(table->record[1],
				       table->record[0])))
    {
      table->file->print_error(error,MYF(0));	/* purecov: inspected */
      DBUG_RETURN(-1);				/* purecov: inspected */
    }
  }
  DBUG_RETURN(0);
}


	/* ARGSUSED */
static int
end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
		bool end_of_records)
{
  TABLE *table=join->tmp_table;
  int	  error;
  int	  idx= -1;
  DBUG_ENTER("end_write_group");

  if (join->thd->killed)
  {						// Aborted by user
unknown's avatar
SCRUM  
unknown committed
10286
    join->thd->send_kill_message();
unknown's avatar
unknown committed
10287 10288 10289 10290 10291 10292 10293 10294 10295
    DBUG_RETURN(-2);				/* purecov: inspected */
  }
  if (!join->first_record || end_of_records ||
      (idx=test_if_group_changed(join->group_fields)) >= 0)
  {
    if (join->first_record || (end_of_records && !join->group))
    {
      if (join->procedure)
	join->procedure->end_group();
unknown's avatar
unknown committed
10296 10297
      int send_group_parts= join->send_group_parts;
      if (idx < send_group_parts)
unknown's avatar
unknown committed
10298 10299
      {
	if (!join->first_record)
10300 10301
	{
	  /* No matching rows for group function */
10302
	  join->clear();
10303
	}
unknown's avatar
unknown committed
10304 10305 10306 10307
        copy_sum_funcs(join->sum_funcs,
                       join->sum_funcs_end[send_group_parts]);
	if (join->having && join->having->val_int() == 0)
          error= -1;
unknown's avatar
unknown committed
10308
        else if ((error= table->file->write_row(table->record[0])))
unknown's avatar
unknown committed
10309
	{
unknown's avatar
unknown committed
10310 10311 10312 10313 10314
	  if (create_myisam_from_heap(join->thd, table,
				      &join->tmp_table_param,
				      error, 0))
	    DBUG_RETURN(-1);		       
        }
unknown's avatar
unknown committed
10315
        if (join->rollup.state != ROLLUP::STATE_NONE)
unknown's avatar
unknown committed
10316 10317
	{
	  if (join->rollup_write_data((uint) (idx+1), table))
unknown's avatar
unknown committed
10318
	    DBUG_RETURN(-1);
unknown's avatar
unknown committed
10319 10320 10321 10322 10323 10324 10325
	}
	if (end_of_records)
	  DBUG_RETURN(0);
      }
    }
    else
    {
10326 10327
      if (end_of_records)
	DBUG_RETURN(0);
unknown's avatar
unknown committed
10328 10329 10330 10331 10332 10333
      join->first_record=1;
      VOID(test_if_group_changed(join->group_fields));
    }
    if (idx < (int) join->send_group_parts)
    {
      copy_fields(&join->tmp_table_param);
unknown's avatar
unknown committed
10334
      copy_funcs(join->tmp_table_param.items_to_copy);
10335 10336
      if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
	DBUG_RETURN(-1);
unknown's avatar
unknown committed
10337 10338 10339 10340 10341 10342 10343 10344 10345 10346 10347 10348 10349 10350
      if (join->procedure)
	join->procedure->add();
      DBUG_RETURN(0);
    }
  }
  if (update_sum_func(join->sum_funcs))
    DBUG_RETURN(-1);
  if (join->procedure)
    join->procedure->add();
  DBUG_RETURN(0);
}


/*****************************************************************************
10351 10352 10353 10354 10355
  Remove calculation with tables that aren't yet read. Remove also tests
  against fields that are read through key where the table is not a
  outer join table.
  We can't remove tests that are made against columns which are stored
  in sorted order.
unknown's avatar
unknown committed
10356 10357 10358 10359 10360 10361 10362
*****************************************************************************/

/* Return 1 if right_item is used removable reference key on left_item */

static bool test_if_ref(Item_field *left_item,Item *right_item)
{
  Field *field=left_item->field;
10363 10364
  // No need to change const test. We also have to keep tests on LEFT JOIN
  if (!field->table->const_table && !field->table->maybe_null)
unknown's avatar
unknown committed
10365 10366
  {
    Item *ref_item=part_of_refkey(field->table,field);
10367
    if (ref_item && ref_item->eq(right_item,1))
unknown's avatar
unknown committed
10368 10369
    {
      if (right_item->type() == Item::FIELD_ITEM)
10370 10371
	return (field->eq_def(((Item_field *) right_item)->field));
      if (right_item->const_item() && !(right_item->is_null()))
unknown's avatar
unknown committed
10372
      {
10373 10374 10375
	/*
	  We can remove binary fields and numerical fields except float,
	  as float comparison isn't 100 % secure
10376
	  We have to keep normal strings to be able to check for end spaces
10377
	*/
unknown's avatar
unknown committed
10378
	if (field->binary() &&
10379 10380
	    field->real_type() != MYSQL_TYPE_STRING &&
	    field->real_type() != MYSQL_TYPE_VARCHAR &&
unknown's avatar
unknown committed
10381 10382 10383 10384 10385 10386 10387 10388 10389 10390 10391 10392
	    (field->type() != FIELD_TYPE_FLOAT || field->decimals() == 0))
	{
	  return !store_val_in_field(field,right_item);
	}
      }
    }
  }
  return 0;					// keep test
}


static COND *
unknown's avatar
af  
unknown committed
10393
make_cond_for_table(COND *cond, table_map tables, table_map used_table)
unknown's avatar
unknown committed
10394 10395 10396 10397 10398 10399 10400
{
  if (used_table && !(cond->used_tables() & used_table))
    return (COND*) 0;				// Already checked
  if (cond->type() == Item::COND_ITEM)
  {
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
    {
10401
      /* Create new top level AND item */
unknown's avatar
unknown committed
10402 10403 10404 10405 10406 10407 10408 10409 10410 10411 10412 10413 10414 10415 10416 10417 10418
      Item_cond_and *new_cond=new Item_cond_and;
      if (!new_cond)
	return (COND*) 0;			// OOM /* purecov: inspected */
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
      Item *item;
      while ((item=li++))
      {
	Item *fix=make_cond_for_table(item,tables,used_table);
	if (fix)
	  new_cond->argument_list()->push_back(fix);
      }
      switch (new_cond->argument_list()->elements) {
      case 0:
	return (COND*) 0;			// Always true
      case 1:
	return new_cond->argument_list()->head();
      default:
unknown's avatar
af  
unknown committed
10419 10420 10421 10422 10423 10424 10425
	/*
	  Item_cond_and do not need fix_fields for execution, its parameters
	  are fixed or do not need fix_fields, too
	*/
	new_cond->quick_fix_field();
	new_cond->used_tables_cache=
	  ((Item_cond_and*) cond)->used_tables_cache &
unknown's avatar
unknown committed
10426 10427 10428 10429 10430 10431 10432 10433 10434 10435 10436 10437 10438 10439 10440 10441 10442 10443
	  tables;
	return new_cond;
      }
    }
    else
    {						// Or list
      Item_cond_or *new_cond=new Item_cond_or;
      if (!new_cond)
	return (COND*) 0;			// OOM /* purecov: inspected */
      List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
      Item *item;
      while ((item=li++))
      {
	Item *fix=make_cond_for_table(item,tables,0L);
	if (!fix)
	  return (COND*) 0;			// Always true
	new_cond->argument_list()->push_back(fix);
      }
unknown's avatar
af  
unknown committed
10444 10445 10446 10447 10448 10449
      /*
	Item_cond_and do not need fix_fields for execution, its parameters
	are fixed or do not need fix_fields, too
      */
      new_cond->quick_fix_field();
      new_cond->used_tables_cache= ((Item_cond_or*) cond)->used_tables_cache;
10450
      new_cond->top_level_item();
unknown's avatar
unknown committed
10451 10452 10453 10454 10455
      return new_cond;
    }
  }

  /*
10456 10457 10458
    Because the following test takes a while and it can be done
    table_count times, we mark each item that we have examined with the result
    of the test
unknown's avatar
unknown committed
10459 10460 10461 10462 10463 10464 10465 10466 10467 10468 10469 10470 10471 10472 10473 10474 10475 10476 10477 10478 10479 10480 10481 10482 10483 10484 10485 10486 10487 10488 10489
  */

  if (cond->marker == 3 || (cond->used_tables() & ~tables))
    return (COND*) 0;				// Can't check this yet
  if (cond->marker == 2 || cond->eq_cmp_result() == Item::COND_OK)
    return cond;				// Not boolean op

  if (((Item_func*) cond)->functype() == Item_func::EQ_FUNC)
  {
    Item *left_item=	((Item_func*) cond)->arguments()[0];
    Item *right_item= ((Item_func*) cond)->arguments()[1];
    if (left_item->type() == Item::FIELD_ITEM &&
	test_if_ref((Item_field*) left_item,right_item))
    {
      cond->marker=3;			// Checked when read
      return (COND*) 0;
    }
    if (right_item->type() == Item::FIELD_ITEM &&
	test_if_ref((Item_field*) right_item,left_item))
    {
      cond->marker=3;			// Checked when read
      return (COND*) 0;
    }
  }
  cond->marker=2;
  return cond;
}

static Item *
part_of_refkey(TABLE *table,Field *field)
{
10490 10491 10492
  if (!table->reginfo.join_tab)
    return (Item*) 0;             // field from outer non-select (UPDATE,...)

unknown's avatar
unknown committed
10493 10494 10495 10496 10497 10498 10499 10500
  uint ref_parts=table->reginfo.join_tab->ref.key_parts;
  if (ref_parts)
  {
    KEY_PART_INFO *key_part=
      table->key_info[table->reginfo.join_tab->ref.key].key_part;

    for (uint part=0 ; part < ref_parts ; part++,key_part++)
      if (field->eq(key_part->field) &&
10501
	  !(key_part->key_part_flag & HA_PART_KEY_SEG))
unknown's avatar
unknown committed
10502 10503 10504 10505 10506 10507 10508
	return table->reginfo.join_tab->ref.items[part];
  }
  return (Item*) 0;
}


/*****************************************************************************
10509
  Test if one can use the key to resolve ORDER BY
10510 10511 10512 10513 10514 10515 10516 10517 10518 10519 10520 10521 10522 10523 10524 10525 10526

  SYNOPSIS
    test_if_order_by_key()
    order		Sort order
    table		Table to sort
    idx			Index to check
    used_key_parts	Return value for used key parts.


  NOTES
    used_key_parts is set to correct key parts used if return value != 0
    (On other cases, used_key_part may be changed)

  RETURN
    1   key is ok.
    0   Key can't be used
    -1  Reverse key can be used
unknown's avatar
unknown committed
10527 10528
*****************************************************************************/

unknown's avatar
unknown committed
10529 10530
static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
				uint *used_key_parts)
unknown's avatar
unknown committed
10531 10532 10533 10534 10535 10536
{
  KEY_PART_INFO *key_part,*key_part_end;
  key_part=table->key_info[idx].key_part;
  key_part_end=key_part+table->key_info[idx].key_parts;
  key_part_map const_key_parts=table->const_key_parts[idx];
  int reverse=0;
unknown's avatar
af  
unknown committed
10537
  DBUG_ENTER("test_if_order_by_key");
unknown's avatar
unknown committed
10538 10539 10540 10541 10542 10543 10544 10545 10546 10547

  for (; order ; order=order->next, const_key_parts>>=1)
  {
    Field *field=((Item_field*) (*order->item))->field;
    int flag;

    /*
      Skip key parts that are constants in the WHERE clause.
      These are already skipped in the ORDER BY by const_expression_in_where()
    */
unknown's avatar
af  
unknown committed
10548 10549 10550
    for (; const_key_parts & 1 ; const_key_parts>>= 1)
      key_part++; 

unknown's avatar
unknown committed
10551
    if (key_part == key_part_end || key_part->field != field)
unknown's avatar
af  
unknown committed
10552
      DBUG_RETURN(0);
unknown's avatar
unknown committed
10553 10554

    /* set flag to 1 if we can use read-next on key, else to -1 */
10555 10556
    flag= ((order->asc == !(key_part->key_part_flag & HA_REVERSE_SORT)) ?
           1 : -1);
unknown's avatar
unknown committed
10557
    if (reverse && flag != reverse)
unknown's avatar
af  
unknown committed
10558
      DBUG_RETURN(0);
unknown's avatar
unknown committed
10559 10560 10561
    reverse=flag;				// Remember if reverse
    key_part++;
  }
unknown's avatar
unknown committed
10562
  *used_key_parts= (uint) (key_part - table->key_info[idx].key_part);
10563 10564 10565
  if (reverse == -1 && !(table->file->index_flags(idx, *used_key_parts-1, 1) &
                         HA_READ_PREV))
    reverse= 0;                                 // Index can't be used
unknown's avatar
af  
unknown committed
10566
  DBUG_RETURN(reverse);
unknown's avatar
unknown committed
10567 10568
}

unknown's avatar
af  
unknown committed
10569

10570
uint find_shortest_key(TABLE *table, const key_map *usable_keys)
unknown's avatar
unknown committed
10571 10572 10573
{
  uint min_length= (uint) ~0;
  uint best= MAX_KEY;
unknown's avatar
unknown committed
10574
  if (!usable_keys->is_clear_all())
unknown's avatar
unknown committed
10575
  {
10576
    for (uint nr=0; nr < table->s->keys ; nr++)
unknown's avatar
unknown committed
10577
    {
unknown's avatar
unknown committed
10578
      if (usable_keys->is_set(nr))
unknown's avatar
unknown committed
10579
      {
10580 10581 10582 10583 10584
        if (table->key_info[nr].key_length < min_length)
        {
          min_length=table->key_info[nr].key_length;
          best=nr;
        }
unknown's avatar
unknown committed
10585 10586 10587 10588 10589 10590
      }
    }
  }
  return best;
}

10591
/*
unknown's avatar
af  
unknown committed
10592 10593
  Test if a second key is the subkey of the first one.

10594 10595
  SYNOPSIS
    is_subkey()
unknown's avatar
af  
unknown committed
10596 10597 10598 10599
    key_part		First key parts
    ref_key_part	Second key parts
    ref_key_part_end	Last+1 part of the second key

10600 10601
  NOTE
    Second key MUST be shorter than the first one.
unknown's avatar
af  
unknown committed
10602

10603
  RETURN
unknown's avatar
af  
unknown committed
10604 10605
    1	is a subkey
    0	no sub key
10606 10607 10608 10609 10610 10611 10612 10613 10614 10615 10616 10617 10618
*/

inline bool 
is_subkey(KEY_PART_INFO *key_part, KEY_PART_INFO *ref_key_part,
	  KEY_PART_INFO *ref_key_part_end)
{
  for (; ref_key_part < ref_key_part_end; key_part++, ref_key_part++)
    if (!key_part->field->eq(ref_key_part->field))
      return 0;
  return 1;
}

/*
unknown's avatar
af  
unknown committed
10619 10620
  Test if we can use one of the 'usable_keys' instead of 'ref' key for sorting

10621 10622
  SYNOPSIS
    test_if_subkey()
unknown's avatar
af  
unknown committed
10623 10624 10625
    ref			Number of key, used for WHERE clause
    usable_keys		Keys for testing

10626
  RETURN
unknown's avatar
af  
unknown committed
10627 10628
    MAX_KEY			If we can't use other key
    the number of found key	Otherwise
10629 10630 10631
*/

static uint
unknown's avatar
unknown committed
10632
test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
unknown's avatar
af  
unknown committed
10633
	       const key_map *usable_keys)
10634 10635 10636 10637 10638 10639 10640
{
  uint nr;
  uint min_length= (uint) ~0;
  uint best= MAX_KEY;
  uint not_used;
  KEY_PART_INFO *ref_key_part= table->key_info[ref].key_part;
  KEY_PART_INFO *ref_key_part_end= ref_key_part + ref_key_parts;
10641

10642
  for (nr= 0 ; nr < table->s->keys ; nr++)
10643
  {
unknown's avatar
af  
unknown committed
10644
    if (usable_keys->is_set(nr) &&
10645 10646 10647 10648 10649 10650 10651 10652 10653 10654 10655 10656
	table->key_info[nr].key_length < min_length &&
	table->key_info[nr].key_parts >= ref_key_parts &&
	is_subkey(table->key_info[nr].key_part, ref_key_part,
		  ref_key_part_end) &&
	test_if_order_by_key(order, table, nr, &not_used))
    {
      min_length= table->key_info[nr].key_length;
      best= nr;
    }
  }
  return best;
}
unknown's avatar
unknown committed
10657

10658 10659 10660 10661 10662 10663 10664 10665 10666 10667
/*
  Test if we can skip the ORDER BY by using an index.

  If we can use an index, the JOIN_TAB / tab->select struct
  is changed to use the index.

  Return:
     0 We have to use filesort to do the sorting
     1 We can use an index.
*/
unknown's avatar
unknown committed
10668 10669

static bool
10670 10671
test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
			bool no_changes)
unknown's avatar
unknown committed
10672 10673
{
  int ref_key;
unknown's avatar
unknown committed
10674
  uint ref_key_parts;
unknown's avatar
unknown committed
10675 10676 10677 10678
  TABLE *table=tab->table;
  SQL_SELECT *select=tab->select;
  key_map usable_keys;
  DBUG_ENTER("test_if_skip_sort_order");
unknown's avatar
unknown committed
10679
  LINT_INIT(ref_key_parts);
unknown's avatar
unknown committed
10680 10681

  /* Check which keys can be used to resolve ORDER BY */
10682
  usable_keys.set_all();
unknown's avatar
unknown committed
10683 10684 10685 10686
  for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
  {
    if ((*tmp_order->item)->type() != Item::FIELD_ITEM)
    {
10687
      usable_keys.clear_all();
unknown's avatar
af  
unknown committed
10688
      DBUG_RETURN(0);
unknown's avatar
unknown committed
10689
    }
unknown's avatar
af  
unknown committed
10690 10691
    usable_keys.intersect(((Item_field*) (*tmp_order->item))->
			  field->part_of_sortkey);
unknown's avatar
unknown committed
10692
    if (usable_keys.is_clear_all())
unknown's avatar
af  
unknown committed
10693
      DBUG_RETURN(0);					// No usable keys
unknown's avatar
unknown committed
10694 10695 10696
  }

  ref_key= -1;
10697
  /* Test if constant range in WHERE */
unknown's avatar
af  
unknown committed
10698
  if (tab->ref.key >= 0 && tab->ref.key_parts)
unknown's avatar
unknown committed
10699 10700 10701
  {
    ref_key=	   tab->ref.key;
    ref_key_parts= tab->ref.key_parts;
10702
    if (tab->type == JT_REF_OR_NULL || tab->type == JT_FT)
10703
      DBUG_RETURN(0);
unknown's avatar
unknown committed
10704
  }
unknown's avatar
unknown committed
10705
  else if (select && select->quick)		// Range found by opt_range
unknown's avatar
unknown committed
10706
  {
unknown's avatar
af  
unknown committed
10707 10708 10709 10710 10711 10712 10713 10714 10715 10716
    int quick_type= select->quick->get_type();
    /* 
      assume results are not ordered when index merge is used 
      TODO: sergeyp: Results of all index merge selects actually are ordered 
      by clustered PK values.
    */
  
    if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE || 
        quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || 
        quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT)
unknown's avatar
unknown committed
10717
      DBUG_RETURN(0);
unknown's avatar
unknown committed
10718 10719 10720
    ref_key=	   select->quick->index;
    ref_key_parts= select->quick->used_key_parts;
  }
unknown's avatar
unknown committed
10721 10722 10723

  if (ref_key >= 0)
  {
10724 10725 10726
    /*
      We come here when there is a REF key.
    */
10727
    int order_direction;
unknown's avatar
unknown committed
10728
    uint used_key_parts;
10729
    if (!usable_keys.is_set(ref_key))
10730 10731 10732 10733
    {
      /*
	We come here when ref_key is not among usable_keys
      */
unknown's avatar
unknown committed
10734 10735 10736 10737 10738
      uint new_ref_key;
      /*
	If using index only read, only consider other possible index only
	keys
      */
10739
      if (table->used_keys.is_set(ref_key))
unknown's avatar
af  
unknown committed
10740
	usable_keys.intersect(table->used_keys);
unknown's avatar
unknown committed
10741
      if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
unknown's avatar
af  
unknown committed
10742
				       &usable_keys)) < MAX_KEY)
10743
      {
unknown's avatar
unknown committed
10744
	/* Found key that can be used to retrieve data in sorted order */
10745 10746
	if (tab->ref.key >= 0)
	{
10747 10748 10749
          /*
            We'll use ref access method on key new_ref_key. In general case 
            the index search tuple for new_ref_key will be different (e.g.
unknown's avatar
unknown committed
10750 10751 10752
            when one index is defined as (part1, part2, ...) and another as
            (part1, part2(N), ...) and the WHERE clause contains 
            "part1 = const1 AND part2=const2". 
10753 10754 10755 10756 10757 10758 10759 10760
            So we build tab->ref from scratch here.
          */
          KEYUSE *keyuse= tab->keyuse;
          while (keyuse->key != new_ref_key && keyuse->table == tab->table)
            keyuse++;
          if (create_ref_for_key(tab->join, tab, keyuse, 
                                 tab->join->const_table_map))
            DBUG_RETURN(0);
10761 10762 10763
	}
	else
	{
10764 10765 10766 10767 10768 10769 10770 10771 10772 10773 10774 10775 10776 10777 10778 10779
          /*
            The range optimizer constructed QUICK_RANGE for ref_key, and
            we want to use instead new_ref_key as the index. We can't
            just change the index of the quick select, because this may
            result in an incosistent QUICK_SELECT object. Below we
            create a new QUICK_SELECT from scratch so that all its
            parameres are set correctly by the range optimizer.
           */
          key_map new_ref_key_map;
          new_ref_key_map.clear_all();  /* Force the creation of quick select */
          new_ref_key_map.set_bit(new_ref_key); /* only for new_ref_key.      */

          if (select->test_quick_select(tab->join->thd, new_ref_key_map, 0,
                                        (tab->join->select_options & OPTION_FOUND_ROWS) ?
                                        HA_POS_ERROR : tab->join->unit->select_limit_cnt) <= 0)
            DBUG_RETURN(0);
10780
	}
unknown's avatar
unknown committed
10781
        ref_key= new_ref_key;
10782
      }
10783
    }
unknown's avatar
unknown committed
10784
    /* Check if we get the rows in requested sorted order by using the key */
10785
    if (usable_keys.is_set(ref_key) &&
unknown's avatar
unknown committed
10786 10787
	(order_direction = test_if_order_by_key(order,table,ref_key,
						&used_key_parts)))
10788
    {
10789
      if (order_direction == -1)		// If ORDER BY ... DESC
10790
      {
unknown's avatar
unknown committed
10791 10792
	if (select && select->quick)
	{
10793 10794 10795 10796 10797
	  /*
	    Don't reverse the sort order, if it's already done.
	    (In some cases test_if_order_by_key() can be called multiple times
	  */
	  if (!select->quick->reverse_sorted())
unknown's avatar
unknown committed
10798
	  {
unknown's avatar
af  
unknown committed
10799
            int quick_type= select->quick->get_type();
unknown's avatar
unknown committed
10800
            if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
unknown's avatar
af  
unknown committed
10801
                quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
10802 10803
                quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
                quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
unknown's avatar
unknown committed
10804
              DBUG_RETURN(0);                   // Use filesort
unknown's avatar
unknown committed
10805
            
unknown's avatar
unknown committed
10806
            /* ORDER BY range_key DESC */
unknown's avatar
unknown committed
10807
	    QUICK_SELECT_DESC *tmp=new QUICK_SELECT_DESC((QUICK_RANGE_SELECT*)(select->quick),
10808 10809 10810 10811 10812 10813 10814
							 used_key_parts);
	    if (!tmp || tmp->error)
	    {
	      delete tmp;
	      DBUG_RETURN(0);		// Reverse sort not supported
	    }
	    select->quick=tmp;
unknown's avatar
unknown committed
10815 10816 10817 10818 10819 10820 10821
	  }
	  DBUG_RETURN(1);
	}
	if (tab->ref.key_parts < used_key_parts)
	{
	  /*
	    SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
10822 10823 10824

	    Use a traversal function that starts by reading the last row
	    with key part (A) and then traverse the index backwards.
unknown's avatar
unknown committed
10825
	  */
10826 10827 10828
	  tab->read_first_record=       join_read_last_key;
	  tab->read_record.read_record= join_read_prev_same;
	  /* fall through */
unknown's avatar
unknown committed
10829
	}
10830
      }
unknown's avatar
af  
unknown committed
10831 10832
      else if (select && select->quick)
	  select->quick->sorted= 1;
unknown's avatar
unknown committed
10833
      DBUG_RETURN(1);			/* No need to sort */
10834
    }
unknown's avatar
unknown committed
10835 10836 10837 10838 10839 10840
  }
  else
  {
    /* check if we can use a key to resolve the group */
    /* Tables using JT_NEXT are handled here */
    uint nr;
10841
    key_map keys;
unknown's avatar
unknown committed
10842 10843 10844 10845 10846 10847 10848

    /*
      If not used with LIMIT, only use keys if the whole query can be
      resolved with a key;  This is because filesort() is usually faster than
      retrieving all rows through an index.
    */
    if (select_limit >= table->file->records)
10849
    {
unknown's avatar
af  
unknown committed
10850
      keys= *table->file->keys_to_use_for_scanning();
10851
      keys.merge(table->used_keys);
unknown's avatar
af  
unknown committed
10852 10853

      /*
10854
	We are adding here also the index specified in FORCE INDEX clause, 
unknown's avatar
af  
unknown committed
10855
	if any.
10856
        This is to allow users to use index in ORDER BY.
unknown's avatar
af  
unknown committed
10857 10858 10859 10860
      */
      if (table->force_index) 
	keys.merge(table->keys_in_use_for_query);
      keys.intersect(usable_keys);
10861 10862
    }
    else
unknown's avatar
af  
unknown committed
10863
      keys= usable_keys;
unknown's avatar
unknown committed
10864

10865
    for (nr=0; nr < table->s->keys ; nr++)
unknown's avatar
unknown committed
10866
    {
unknown's avatar
unknown committed
10867
      uint not_used;
10868
      if (keys.is_set(nr))
unknown's avatar
unknown committed
10869 10870
      {
	int flag;
unknown's avatar
unknown committed
10871
	if ((flag= test_if_order_by_key(order, table, nr, &not_used)))
unknown's avatar
unknown committed
10872
	{
10873 10874 10875
	  if (!no_changes)
	  {
	    tab->index=nr;
10876 10877
	    tab->read_first_record=  (flag > 0 ? join_read_first:
				      join_read_last);
10878
	    tab->type=JT_NEXT;	// Read with index_first(), index_next()
10879
	    if (table->used_keys.is_set(nr))
unknown's avatar
unknown committed
10880 10881 10882 10883
	    {
	      table->key_read=1;
	      table->file->extra(HA_EXTRA_KEYREAD);
	    }
10884
	  }
unknown's avatar
unknown committed
10885 10886 10887 10888 10889 10890 10891 10892
	  DBUG_RETURN(1);
	}
      }
    }
  }
  DBUG_RETURN(0);				// Can't use index.
}

unknown's avatar
unknown committed
10893

unknown's avatar
unknown committed
10894
/*
unknown's avatar
unknown committed
10895
  If not selecting by given key, create an index how records should be read
unknown's avatar
unknown committed
10896 10897 10898 10899 10900 10901 10902 10903

  SYNOPSIS
   create_sort_index()
     thd		Thread handler
     tab		Table to sort (in join structure)
     order		How table should be sorted
     filesort_limit	Max number of rows that needs to be sorted
     select_limit	Max number of rows in final output
10904
		        Used to decide if we should use index or not
unknown's avatar
unknown committed
10905 10906 10907 10908 10909 10910 10911 10912 10913 10914 10915 10916 10917 10918 10919


  IMPLEMENTATION
   - If there is an index that can be used, 'tab' 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).

  RETURN VALUES
    0		ok
    -1		Some fatal error
    1		No records
*/
unknown's avatar
unknown committed
10920

unknown's avatar
unknown committed
10921
static int
10922
create_sort_index(THD *thd, JOIN *join, ORDER *order,
unknown's avatar
unknown committed
10923
		  ha_rows filesort_limit, ha_rows select_limit)
unknown's avatar
unknown committed
10924 10925 10926
{
  SORT_FIELD *sortorder;
  uint length;
10927
  ha_rows examined_rows;
10928 10929 10930
  TABLE *table;
  SQL_SELECT *select;
  JOIN_TAB *tab;
unknown's avatar
unknown committed
10931 10932
  DBUG_ENTER("create_sort_index");

10933 10934 10935 10936 10937 10938
  if (join->tables == join->const_tables)
    DBUG_RETURN(0);				// One row, no need to sort
  tab=    join->join_tab + join->const_tables;
  table=  tab->table;
  select= tab->select;

10939
  if (test_if_skip_sort_order(tab,order,select_limit,0))
unknown's avatar
unknown committed
10940 10941 10942 10943
    DBUG_RETURN(0);
  if (!(sortorder=make_unireg_sortorder(order,&length)))
    goto err;				/* purecov: inspected */
  /* It's not fatal if the following alloc fails */
unknown's avatar
unknown committed
10944 10945
  table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
                                             MYF(MY_WME | MY_ZEROFILL));
unknown's avatar
unknown committed
10946 10947 10948 10949 10950 10951 10952 10953 10954
  table->status=0;				// May be wrong if quick_select

  // If table has a range, move it to select
  if (select && !select->quick && tab->ref.key >= 0)
  {
    if (tab->quick)
    {
      select->quick=tab->quick;
      tab->quick=0;
unknown's avatar
unknown committed
10955 10956 10957 10958 10959
      /* 
        We can only use 'Only index' if quick key is same as ref_key
        and in index_merge 'Only index' cannot be used
      */
      if (table->key_read && ((uint) tab->ref.key != select->quick->index))
unknown's avatar
unknown committed
10960 10961 10962 10963 10964 10965 10966 10967 10968 10969
      {
	table->key_read=0;
	table->file->extra(HA_EXTRA_NO_KEYREAD);
      }
    }
    else
    {
      /*
	We have a ref on a const;  Change this to a range that filesort
	can use.
10970 10971
	For impossible ranges (like when doing a lookup on NULL on a NOT NULL
	field, quick will contain an empty record set.
unknown's avatar
unknown committed
10972
      */
unknown's avatar
af  
unknown committed
10973 10974 10975
      if (!(select->quick= (tab->type == JT_FT ?
			    new FT_SELECT(thd, table, tab->ref.key) :
			    get_quick_select_for_ref(thd, table, &tab->ref))))
unknown's avatar
unknown committed
10976 10977 10978
	goto err;
    }
  }
10979
  if (table->s->tmp_table)
10980
    table->file->info(HA_STATUS_VARIABLE);	// Get record count
unknown's avatar
unknown committed
10981 10982
  table->sort.found_records=filesort(thd, table,sortorder, length,
                                     select, filesort_limit, &examined_rows);
unknown's avatar
af  
unknown committed
10983 10984 10985 10986 10987 10988
  tab->records= table->sort.found_records;	// For SQL_CALC_ROWS
  if (select)
  {
    select->cleanup();				// filesort did select
    tab->select= 0;
  }
unknown's avatar
unknown committed
10989
  tab->select_cond=0;
10990 10991
  tab->last_inner= 0;
  tab->first_unmatched= 0;
unknown's avatar
unknown committed
10992 10993
  tab->type=JT_ALL;				// Read with normal read_record
  tab->read_first_record= join_init_read_record;
10994
  tab->join->examined_rows+=examined_rows;
unknown's avatar
unknown committed
10995 10996 10997 10998 10999
  if (table->key_read)				// Restore if we used indexes
  {
    table->key_read=0;
    table->file->extra(HA_EXTRA_NO_KEYREAD);
  }
unknown's avatar
unknown committed
11000
  DBUG_RETURN(table->sort.found_records == HA_POS_ERROR);
unknown's avatar
unknown committed
11001 11002 11003 11004
err:
  DBUG_RETURN(-1);
}

11005
/*
11006
  Add the HAVING criteria to table->select
11007 11008
*/

unknown's avatar
unknown committed
11009
#ifdef NOT_YET
11010 11011 11012 11013 11014 11015
static bool fix_having(JOIN *join, Item **having)
{
  (*having)->update_used_tables();	// Some tables may have been const
  JOIN_TAB *table=&join->join_tab[join->const_tables];
  table_map used_tables= join->const_table_map | table->table->map;

unknown's avatar
unknown committed
11016
  DBUG_EXECUTE("where",print_where(*having,"having"););
11017 11018 11019 11020 11021 11022 11023 11024 11025
  Item* sort_table_cond=make_cond_for_table(*having,used_tables,used_tables);
  if (sort_table_cond)
  {
    if (!table->select)
      if (!(table->select=new SQL_SELECT))
	return 1;
    if (!table->select->cond)
      table->select->cond=sort_table_cond;
    else					// This should never happen
unknown's avatar
af  
unknown committed
11026 11027 11028 11029
      if (!(table->select->cond= new Item_cond_and(table->select->cond,
						   sort_table_cond)) ||
	  table->select->cond->fix_fields(join->thd, join->tables_list,
					  &table->select->cond))
11030 11031
	return 1;
    table->select_cond=table->select->cond;
11032
    table->select_cond->top_level_item();
11033 11034 11035 11036 11037 11038 11039
    DBUG_EXECUTE("where",print_where(table->select_cond,
				     "select and having"););
    *having=make_cond_for_table(*having,~ (table_map) 0,~used_tables);
    DBUG_EXECUTE("where",print_where(*having,"having after make_cond"););
  }
  return 0;
}
unknown's avatar
unknown committed
11040
#endif
11041 11042


unknown's avatar
unknown committed
11043
/*****************************************************************************
11044 11045 11046 11047 11048
  Remove duplicates from tmp table
  This should be recoded to add a unique index to the table and remove
  duplicates
  Table is a locked single thread table
  fields is the number of fields to check (from the end)
unknown's avatar
unknown committed
11049 11050 11051 11052 11053 11054
*****************************************************************************/

static bool compare_record(TABLE *table, Field **ptr)
{
  for (; *ptr ; ptr++)
  {
11055
    if ((*ptr)->cmp_offset(table->s->rec_buff_length))
unknown's avatar
unknown committed
11056 11057 11058 11059 11060 11061 11062 11063 11064 11065 11066 11067 11068 11069 11070 11071 11072 11073 11074 11075 11076 11077 11078 11079 11080 11081 11082
      return 1;
  }
  return 0;
}

static bool copy_blobs(Field **ptr)
{
  for (; *ptr ; ptr++)
  {
    if ((*ptr)->flags & BLOB_FLAG)
      if (((Field_blob *) (*ptr))->copy())
	return 1;				// Error
  }
  return 0;
}

static void free_blobs(Field **ptr)
{
  for (; *ptr ; ptr++)
  {
    if ((*ptr)->flags & BLOB_FLAG)
      ((Field_blob *) (*ptr))->free();
  }
}


static int
11083
remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
unknown's avatar
unknown committed
11084 11085 11086 11087
{
  int error;
  ulong reclength,offset;
  uint field_count;
11088
  THD *thd= join->thd;
unknown's avatar
unknown committed
11089 11090 11091 11092 11093 11094 11095 11096 11097
  DBUG_ENTER("remove_duplicates");

  entry->reginfo.lock_type=TL_WRITE;

  /* Calculate how many saved fields there is in list */
  field_count=0;
  List_iterator<Item> it(fields);
  Item *item;
  while ((item=it++))
unknown's avatar
unknown committed
11098
  {
11099
    if (item->get_tmp_table_field() && ! item->const_item())
unknown's avatar
unknown committed
11100
      field_count++;
unknown's avatar
unknown committed
11101
  }
unknown's avatar
unknown committed
11102

11103 11104
  if (!field_count && !(join->select_options & OPTION_FOUND_ROWS)) 
  {                    // only const items with no OPTION_FOUND_ROWS
11105
    join->unit->select_limit_cnt= 1;		// Only send first row
unknown's avatar
unknown committed
11106 11107
    DBUG_RETURN(0);
  }
11108
  Field **first_field=entry->field+entry->s->fields - field_count;
11109
  offset= field_count ? 
unknown's avatar
unknown committed
11110
          entry->field[entry->s->fields - field_count]->offset() : 0;
11111
  reclength=entry->s->reclength-offset;
unknown's avatar
unknown committed
11112 11113 11114

  free_io_cache(entry);				// Safety
  entry->file->info(HA_STATUS_VARIABLE);
11115 11116
  if (entry->s->db_type == DB_TYPE_HEAP ||
      (!entry->s->blob_fields &&
unknown's avatar
unknown committed
11117
       ((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->file->records <
11118
	thd->variables.sortbuff_size)))
unknown's avatar
unknown committed
11119 11120
    error=remove_dup_with_hash_index(join->thd, entry,
				     field_count, first_field,
11121
				     reclength, having);
unknown's avatar
unknown committed
11122
  else
11123 11124
    error=remove_dup_with_compare(join->thd, entry, first_field, offset,
				  having);
unknown's avatar
unknown committed
11125 11126 11127 11128 11129 11130 11131

  free_blobs(first_field);
  DBUG_RETURN(error);
}


static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
11132
				   ulong offset, Item *having)
unknown's avatar
unknown committed
11133 11134 11135
{
  handler *file=table->file;
  char *org_record,*new_record;
unknown's avatar
unknown committed
11136
  byte *record;
unknown's avatar
unknown committed
11137
  int error;
11138
  ulong reclength= table->s->reclength-offset;
unknown's avatar
unknown committed
11139 11140
  DBUG_ENTER("remove_dup_with_compare");

11141
  org_record=(char*) (record=table->record[0])+offset;
unknown's avatar
unknown committed
11142 11143
  new_record=(char*) table->record[1]+offset;

11144
  file->ha_rnd_init(1);
11145
  error=file->rnd_next(record);
unknown's avatar
unknown committed
11146 11147 11148 11149
  for (;;)
  {
    if (thd->killed)
    {
unknown's avatar
SCRUM  
unknown committed
11150
      thd->send_kill_message();
unknown's avatar
unknown committed
11151 11152 11153 11154 11155 11156 11157 11158 11159 11160 11161
      error=0;
      goto err;
    }
    if (error)
    {
      if (error == HA_ERR_RECORD_DELETED)
	continue;
      if (error == HA_ERR_END_OF_FILE)
	break;
      goto err;
    }
11162 11163 11164 11165
    if (having && !having->val_int())
    {
      if ((error=file->delete_row(record)))
	goto err;
11166
      error=file->rnd_next(record);
11167 11168
      continue;
    }
unknown's avatar
unknown committed
11169 11170
    if (copy_blobs(first_field))
    {
unknown's avatar
unknown committed
11171
      my_message(ER_OUTOFMEMORY, ER(ER_OUTOFMEMORY), MYF(0));
unknown's avatar
unknown committed
11172 11173 11174 11175 11176 11177 11178 11179 11180
      error=0;
      goto err;
    }
    memcpy(new_record,org_record,reclength);

    /* Read through rest of file and mark duplicated rows deleted */
    bool found=0;
    for (;;)
    {
11181
      if ((error=file->rnd_next(record)))
unknown's avatar
unknown committed
11182 11183 11184 11185 11186 11187 11188 11189 11190
      {
	if (error == HA_ERR_RECORD_DELETED)
	  continue;
	if (error == HA_ERR_END_OF_FILE)
	  break;
	goto err;
      }
      if (compare_record(table, first_field) == 0)
      {
11191
	if ((error=file->delete_row(record)))
unknown's avatar
unknown committed
11192 11193 11194 11195 11196
	  goto err;
      }
      else if (!found)
      {
	found=1;
11197
	file->position(record);	// Remember position
unknown's avatar
unknown committed
11198 11199 11200 11201 11202
      }
    }
    if (!found)
      break;					// End of file
    /* Restart search on next row */
11203
    error=file->restart_rnd_next(record,file->ref);
unknown's avatar
unknown committed
11204 11205 11206 11207 11208 11209 11210 11211 11212 11213 11214 11215 11216 11217 11218 11219 11220 11221 11222 11223
  }

  file->extra(HA_EXTRA_NO_CACHE);
  DBUG_RETURN(0);
err:
  file->extra(HA_EXTRA_NO_CACHE);
  if (error)
    file->print_error(error,MYF(0));
  DBUG_RETURN(1);
}


/*
  Generate a hash index for each row to quickly find duplicate rows
  Note that this will not work on tables with blobs!
*/

static int remove_dup_with_hash_index(THD *thd, TABLE *table,
				      uint field_count,
				      Field **first_field,
11224 11225
				      ulong key_length,
				      Item *having)
unknown's avatar
unknown committed
11226 11227 11228
{
  byte *key_buffer, *key_pos, *record=table->record[0];
  int error;
11229 11230
  handler *file= table->file;
  ulong extra_length= ALIGN_SIZE(key_length)-key_length;
unknown's avatar
unknown committed
11231 11232 11233 11234 11235 11236 11237 11238 11239 11240 11241 11242
  uint *field_lengths,*field_length;
  HASH hash;
  DBUG_ENTER("remove_dup_with_hash_index");

  if (!my_multi_malloc(MYF(MY_WME),
		       &key_buffer,
		       (uint) ((key_length + extra_length) *
			       (long) file->records),
		       &field_lengths,
		       (uint) (field_count*sizeof(*field_lengths)),
		       NullS))
    DBUG_RETURN(1);
unknown's avatar
unknown committed
11243

11244 11245 11246 11247 11248 11249 11250 11251 11252 11253 11254 11255 11256 11257 11258 11259
  {
    Field **ptr;
    ulong total_length= 0;
    for (ptr= first_field, field_length=field_lengths ; *ptr ; ptr++)
    {
      uint length= (*ptr)->pack_length();
      (*field_length++)= length;
      total_length+= length;
    }
    DBUG_PRINT("info",("field_count: %u  key_length: %lu  total_length: %lu",
                       field_count, key_length, total_length));
    DBUG_ASSERT(total_length <= key_length);
    key_length= total_length;
    extra_length= ALIGN_SIZE(key_length)-key_length;
  }

unknown's avatar
unknown committed
11260
  if (hash_init(&hash, &my_charset_bin, (uint) file->records, 0, 
11261
		key_length, (hash_get_key) 0, 0, 0))
unknown's avatar
unknown committed
11262 11263 11264 11265 11266
  {
    my_free((char*) key_buffer,MYF(0));
    DBUG_RETURN(1);
  }

11267
  file->ha_rnd_init(1);
unknown's avatar
unknown committed
11268 11269 11270
  key_pos=key_buffer;
  for (;;)
  {
11271
    byte *org_key_pos;
unknown's avatar
unknown committed
11272 11273
    if (thd->killed)
    {
unknown's avatar
SCRUM  
unknown committed
11274
      thd->send_kill_message();
unknown's avatar
unknown committed
11275 11276 11277 11278 11279 11280 11281 11282 11283 11284 11285
      error=0;
      goto err;
    }
    if ((error=file->rnd_next(record)))
    {
      if (error == HA_ERR_RECORD_DELETED)
	continue;
      if (error == HA_ERR_END_OF_FILE)
	break;
      goto err;
    }
11286 11287 11288 11289 11290
    if (having && !having->val_int())
    {
      if ((error=file->delete_row(record)))
	goto err;
      continue;
11291
    }
unknown's avatar
unknown committed
11292 11293

    /* copy fields to key buffer */
11294
    org_key_pos= key_pos;
unknown's avatar
unknown committed
11295 11296 11297 11298 11299 11300 11301
    field_length=field_lengths;
    for (Field **ptr= first_field ; *ptr ; ptr++)
    {
      (*ptr)->sort_string((char*) key_pos,*field_length);
      key_pos+= *field_length++;
    }
    /* Check if it exists before */
11302
    if (hash_search(&hash, org_key_pos, key_length))
unknown's avatar
unknown committed
11303 11304 11305 11306 11307
    {
      /* Duplicated found ; Remove the row */
      if ((error=file->delete_row(record)))
	goto err;
    }
11308
    else
11309
      (void) my_hash_insert(&hash, org_key_pos);
unknown's avatar
unknown committed
11310 11311 11312 11313 11314
    key_pos+=extra_length;
  }
  my_free((char*) key_buffer,MYF(0));
  hash_free(&hash);
  file->extra(HA_EXTRA_NO_CACHE);
unknown's avatar
unknown committed
11315
  (void) file->ha_rnd_end();
unknown's avatar
unknown committed
11316 11317 11318 11319 11320 11321
  DBUG_RETURN(0);

err:
  my_free((char*) key_buffer,MYF(0));
  hash_free(&hash);
  file->extra(HA_EXTRA_NO_CACHE);
unknown's avatar
unknown committed
11322
  (void) file->ha_rnd_end();
unknown's avatar
unknown committed
11323 11324 11325 11326 11327 11328
  if (error)
    file->print_error(error,MYF(0));
  DBUG_RETURN(1);
}


unknown's avatar
unknown committed
11329
SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
unknown's avatar
unknown committed
11330 11331 11332 11333 11334 11335 11336 11337 11338 11339 11340 11341 11342 11343 11344 11345 11346 11347 11348
{
  uint count;
  SORT_FIELD *sort,*pos;
  DBUG_ENTER("make_unireg_sortorder");

  count=0;
  for (ORDER *tmp = order; tmp; tmp=tmp->next)
    count++;
  pos=sort=(SORT_FIELD*) sql_alloc(sizeof(SORT_FIELD)*(count+1));
  if (!pos)
    return 0;

  for (;order;order=order->next,pos++)
  {
    pos->field=0; pos->item=0;
    if (order->item[0]->type() == Item::FIELD_ITEM)
      pos->field= ((Item_field*) (*order->item))->field;
    else if (order->item[0]->type() == Item::SUM_FUNC_ITEM &&
	     !order->item[0]->const_item())
11349
      pos->field= ((Item_sum*) order->item[0])->get_tmp_table_field();
unknown's avatar
unknown committed
11350 11351 11352 11353 11354 11355 11356 11357 11358 11359 11360 11361 11362 11363
    else if (order->item[0]->type() == Item::COPY_STR_ITEM)
    {						// Blob patch
      pos->item= ((Item_copy_string*) (*order->item))->item;
    }
    else
      pos->item= *order->item;
    pos->reverse=! order->asc;
  }
  *length=count;
  DBUG_RETURN(sort);
}


/*****************************************************************************
11364 11365 11366 11367
  Fill join cache with packed records
  Records are stored in tab->cache.buffer and last record in
  last record is stored with pointers to blobs to support very big
  records
unknown's avatar
unknown committed
11368 11369 11370 11371 11372 11373 11374 11375 11376
******************************************************************************/

static int
join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
{
  reg1 uint i;
  uint length,blobs,size;
  CACHE_FIELD *copy,**blob_ptr;
  JOIN_CACHE  *cache;
11377
  JOIN_TAB *join_tab;
unknown's avatar
unknown committed
11378 11379 11380 11381 11382
  DBUG_ENTER("join_init_cache");

  cache= &tables[table_count].cache;
  cache->fields=blobs=0;

11383 11384
  join_tab=tables;
  for (i=0 ; i < table_count ; i++,join_tab++)
unknown's avatar
unknown committed
11385
  {
11386 11387 11388 11389
    if (!join_tab->used_fieldlength)		/* Not calced yet */
      calc_used_field_length(thd, join_tab);
    cache->fields+=join_tab->used_fields;
    blobs+=join_tab->used_blobs;
unknown's avatar
unknown committed
11390 11391 11392
  }
  if (!(cache->field=(CACHE_FIELD*)
	sql_alloc(sizeof(CACHE_FIELD)*(cache->fields+table_count*2)+(blobs+1)*
unknown's avatar
unknown committed
11393

unknown's avatar
unknown committed
11394 11395 11396 11397 11398 11399 11400 11401 11402 11403 11404 11405 11406 11407 11408 11409 11410 11411 11412 11413 11414 11415 11416 11417 11418 11419 11420 11421 11422 11423 11424 11425 11426
		  sizeof(CACHE_FIELD*))))
  {
    my_free((gptr) cache->buff,MYF(0));		/* purecov: inspected */
    cache->buff=0;				/* purecov: inspected */
    DBUG_RETURN(1);				/* purecov: inspected */
  }
  copy=cache->field;
  blob_ptr=cache->blob_ptr=(CACHE_FIELD**)
    (cache->field+cache->fields+table_count*2);

  length=0;
  for (i=0 ; i < table_count ; i++)
  {
    uint null_fields=0,used_fields;

    Field **f_ptr,*field;
    for (f_ptr=tables[i].table->field,used_fields=tables[i].used_fields ;
	 used_fields ;
	 f_ptr++)
    {
      field= *f_ptr;
      if (field->query_id == thd->query_id)
      {
	used_fields--;
	length+=field->fill_cache_field(copy);
	if (copy->blob_field)
	  (*blob_ptr++)=copy;
	if (field->maybe_null())
	  null_fields++;
	copy++;
      }
    }
    /* Copy null bits from table */
11427
    if (null_fields && tables[i].table->s->null_fields)
unknown's avatar
unknown committed
11428 11429
    {						/* must copy null bits */
      copy->str=(char*) tables[i].table->null_flags;
11430
      copy->length= tables[i].table->s->null_bytes;
unknown's avatar
unknown committed
11431 11432 11433 11434 11435 11436 11437 11438 11439 11440 11441 11442 11443 11444 11445 11446 11447 11448 11449 11450 11451 11452
      copy->strip=0;
      copy->blob_field=0;
      length+=copy->length;
      copy++;
      cache->fields++;
    }
    /* If outer join table, copy null_row flag */
    if (tables[i].table->maybe_null)
    {
      copy->str= (char*) &tables[i].table->null_row;
      copy->length=sizeof(tables[i].table->null_row);
      copy->strip=0;
      copy->blob_field=0;
      length+=copy->length;
      copy++;
      cache->fields++;
    }
  }

  cache->length=length+blobs*sizeof(char*);
  cache->blobs=blobs;
  *blob_ptr=0;					/* End sequentel */
11453
  size=max(thd->variables.join_buff_size, cache->length);
unknown's avatar
unknown committed
11454 11455 11456
  if (!(cache->buff=(uchar*) my_malloc(size,MYF(0))))
    DBUG_RETURN(1);				/* Don't use cache */ /* purecov: inspected */
  cache->end=cache->buff+size;
11457
  reset_cache_write(cache);
unknown's avatar
unknown committed
11458 11459 11460 11461 11462 11463 11464 11465 11466 11467 11468 11469 11470 11471 11472 11473 11474 11475 11476 11477 11478 11479 11480 11481 11482 11483 11484 11485 11486 11487 11488 11489 11490 11491 11492 11493
  DBUG_RETURN(0);
}


static ulong
used_blob_length(CACHE_FIELD **ptr)
{
  uint length,blob_length;
  for (length=0 ; *ptr ; ptr++)
  {
    (*ptr)->blob_length=blob_length=(*ptr)->blob_field->get_length();
    length+=blob_length;
    (*ptr)->blob_field->get_ptr(&(*ptr)->str);
  }
  return length;
}


static bool
store_record_in_cache(JOIN_CACHE *cache)
{
  ulong length;
  uchar *pos;
  CACHE_FIELD *copy,*end_field;
  bool last_record;

  pos=cache->pos;
  end_field=cache->field+cache->fields;

  length=cache->length;
  if (cache->blobs)
    length+=used_blob_length(cache->blob_ptr);
  if ((last_record=(length+cache->length > (uint) (cache->end - pos))))
    cache->ptr_record=cache->records;

  /*
11494
    There is room in cache. Put record there
unknown's avatar
unknown committed
11495 11496 11497 11498 11499 11500 11501 11502
  */
  cache->records++;
  for (copy=cache->field ; copy < end_field; copy++)
  {
    if (copy->blob_field)
    {
      if (last_record)
      {
unknown's avatar
unknown committed
11503 11504
	copy->blob_field->get_image((char*) pos,copy->length+sizeof(char*), 
				    copy->blob_field->charset());
unknown's avatar
unknown committed
11505 11506 11507 11508
	pos+=copy->length+sizeof(char*);
      }
      else
      {
unknown's avatar
unknown committed
11509 11510
	copy->blob_field->get_image((char*) pos,copy->length, // blob length
				    copy->blob_field->charset());
unknown's avatar
unknown committed
11511 11512 11513 11514 11515 11516 11517 11518 11519 11520 11521 11522 11523 11524 11525 11526 11527 11528 11529 11530 11531 11532 11533 11534 11535 11536 11537 11538 11539 11540
	memcpy(pos+copy->length,copy->str,copy->blob_length);  // Blob data
	pos+=copy->length+copy->blob_length;
      }
    }
    else
    {
      if (copy->strip)
      {
	char *str,*end;
	for (str=copy->str,end= str+copy->length;
	     end > str && end[-1] == ' ' ;
	     end--) ;
	length=(uint) (end-str);
	memcpy(pos+1,str,length);
	*pos=(uchar) length;
	pos+=length+1;
      }
      else
      {
	memcpy(pos,copy->str,copy->length);
	pos+=copy->length;
      }
    }
  }
  cache->pos=pos;
  return last_record || (uint) (cache->end -pos) < cache->length;
}


static void
11541
reset_cache_read(JOIN_CACHE *cache)
unknown's avatar
unknown committed
11542 11543 11544 11545 11546 11547
{
  cache->record_nr=0;
  cache->pos=cache->buff;
}


11548 11549 11550 11551 11552
static void reset_cache_write(JOIN_CACHE *cache)
{
  reset_cache_read(cache);
  cache->records= 0;
  cache->ptr_record= (uint) ~0;
unknown's avatar
unknown committed
11553 11554 11555 11556 11557 11558 11559 11560 11561 11562 11563 11564 11565 11566 11567 11568 11569 11570 11571 11572 11573 11574
}


static void
read_cached_record(JOIN_TAB *tab)
{
  uchar *pos;
  uint length;
  bool last_record;
  CACHE_FIELD *copy,*end_field;

  last_record=tab->cache.record_nr++ == tab->cache.ptr_record;
  pos=tab->cache.pos;

  for (copy=tab->cache.field,end_field=copy+tab->cache.fields ;
       copy < end_field;
       copy++)
  {
    if (copy->blob_field)
    {
      if (last_record)
      {
unknown's avatar
unknown committed
11575 11576
	copy->blob_field->set_image((char*) pos,copy->length+sizeof(char*),
				    copy->blob_field->charset());
unknown's avatar
unknown committed
11577 11578 11579 11580 11581 11582 11583 11584 11585 11586 11587 11588 11589 11590 11591 11592 11593 11594 11595 11596 11597 11598 11599 11600 11601 11602 11603 11604 11605 11606 11607 11608 11609 11610 11611 11612
	pos+=copy->length+sizeof(char*);
      }
      else
      {
	copy->blob_field->set_ptr((char*) pos,(char*) pos+copy->length);
	pos+=copy->length+copy->blob_field->get_length();
      }
    }
    else
    {
      if (copy->strip)
      {
	memcpy(copy->str,pos+1,length=(uint) *pos);
	memset(copy->str+length,' ',copy->length-length);
	pos+=1+length;
      }
      else
      {
	memcpy(copy->str,pos,copy->length);
	pos+=copy->length;
      }
    }
  }
  tab->cache.pos=pos;
  return;
}


static bool
cmp_buffer_with_ref(JOIN_TAB *tab)
{
  bool diff;
  if (!(diff=tab->ref.key_err))
  {
    memcpy(tab->ref.key_buff2, tab->ref.key_buff, tab->ref.key_length);
  }
unknown's avatar
unknown committed
11613 11614
  if ((tab->ref.key_err= cp_buffer_from_ref(tab->join->thd, &tab->ref)) || 
      diff)
unknown's avatar
unknown committed
11615 11616 11617 11618 11619 11620 11621
    return 1;
  return memcmp(tab->ref.key_buff2, tab->ref.key_buff, tab->ref.key_length)
    != 0;
}


bool
unknown's avatar
unknown committed
11622
cp_buffer_from_ref(THD *thd, TABLE_REF *ref)
unknown's avatar
unknown committed
11623
{
unknown's avatar
unknown committed
11624 11625
  enum enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
  thd->count_cuted_fields= CHECK_FIELD_IGNORE;
unknown's avatar
unknown committed
11626 11627
  for (store_key **copy=ref->key_copy ; *copy ; copy++)
    if ((*copy)->copy())
unknown's avatar
unknown committed
11628 11629
    {
      thd->count_cuted_fields= save_count_cuted_fields;
unknown's avatar
unknown committed
11630
      return 1;					// Something went wrong
unknown's avatar
unknown committed
11631 11632
    }
  thd->count_cuted_fields= save_count_cuted_fields;
unknown's avatar
unknown committed
11633 11634 11635 11636 11637
  return 0;
}


/*****************************************************************************
11638
  Group and order functions
unknown's avatar
unknown committed
11639 11640 11641
*****************************************************************************/

/*
11642 11643 11644 11645 11646 11647 11648 11649 11650 11651 11652 11653 11654 11655 11656 11657 11658 11659 11660 11661 11662 11663 11664 11665 11666 11667
  Resolve an ORDER BY or GROUP BY column reference.

  SYNOPSIS
    find_order_in_list()
    thd		      [in]     Pointer to current thread structure
    ref_pointer_array [in/out] All select, group and order by fields
    tables            [in]     List of tables to search in (usually FROM clause)
    order             [in]     Column reference to be resolved
    fields            [in]     List of fields to search in (usually SELECT list)
    all_fields        [in/out] All select, group and order by fields
    is_group_field    [in]     True if order is a GROUP field, false if
                               ORDER by field

  DESCRIPTION
    Given a column reference (represented by 'order') from a GROUP BY or ORDER
    BY clause, find the actual column it represents. If the column being
    resolved is from the GROUP BY clause, the procedure searches the SELECT
    list 'fields' and the columns in the FROM list 'tables'. If 'order' is from
    the ORDER BY clause, only the SELECT list is being searched.

    If 'order' is resolved to an Item, then order->item is set to the found
    Item. If there is no item for the found column (that is, it was resolved
    into a table field), order->item is 'fixed' and is added to all_fields and
    ref_pointer_array.

  RETURN
unknown's avatar
unknown committed
11668
    0 if OK
11669
    1 if error occurred
unknown's avatar
unknown committed
11670 11671 11672
*/

static int
11673 11674 11675
find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
                   ORDER *order, List<Item> &fields, List<Item> &all_fields,
                   bool is_group_field)
unknown's avatar
unknown committed
11676
{
11677
  Item *order_item= *order->item; /* The item from the GROUP/ORDER caluse. */
11678 11679 11680 11681 11682
  Item::Type order_item_type;
  Item **select_item; /* The corresponding item from the SELECT clause. */
  Field *from_field;  /* The corresponding field from the FROM clause. */

  if (order_item->type() == Item::INT_ITEM)
unknown's avatar
unknown committed
11683
  {						/* Order by position */
11684
    uint count= (uint) order_item->val_int();
unknown's avatar
unknown committed
11685
    if (!count || count > fields.elements)
unknown's avatar
unknown committed
11686
    {
11687 11688
      my_error(ER_BAD_FIELD_ERROR, MYF(0),
               order_item->full_name(), thd->where);
unknown's avatar
unknown committed
11689 11690
      return 1;
    }
11691
    order->item= ref_pointer_array + count - 1;
11692
    order->in_field_list= 1;
11693 11694
    order->counter= count;
    order->counter_used= 1;
unknown's avatar
unknown committed
11695 11696
    return 0;
  }
11697
  /* Lookup the current GROUP/ORDER field in the SELECT clause. */
11698
  uint counter;
11699
  bool unaliased;
11700
  select_item= find_item_in_list(order_item, fields, &counter,
11701
                                 REPORT_EXCEPT_NOT_FOUND, &unaliased);
11702 11703
  if (!select_item)
    return 1; /* Some error occured. */
11704 11705


11706 11707
  /* Check whether the resolved field is not ambiguos. */
  if (select_item != not_found_item)
unknown's avatar
unknown committed
11708
  {
11709
    Item *view_ref= NULL;
11710 11711 11712 11713 11714
    /*
      If we have found field not by its alias in select list but by its
      original field name, we should additionaly check if we have conflict
      for this name (in case if we would perform lookup in all tables).
    */
11715 11716
    if (unaliased && !order_item->fixed && order_item->fix_fields(thd, tables,
                                                                  order->item))
11717 11718
      return 1;

11719 11720 11721
    /* Lookup the current GROUP field in the FROM clause. */
    order_item_type= order_item->type();
    if (is_group_field &&
11722 11723
        order_item_type == Item::FIELD_ITEM ||
        order_item_type == Item::REF_ITEM)
11724 11725
    {
      from_field= find_field_in_tables(thd, (Item_ident*) order_item, tables,
11726
                                       &view_ref, IGNORE_ERRORS, TRUE);
11727 11728 11729 11730 11731 11732 11733
      if(!from_field)
       from_field= (Field*) not_found_field;
    }
    else
      from_field= (Field*) not_found_field;

    if (from_field == not_found_field ||
11734 11735 11736 11737 11738 11739 11740 11741 11742
        from_field &&
        (from_field != view_ref_found ?
         /* it is field of base table => check that fields are same */
         ((*select_item)->type() == Item::FIELD_ITEM &&
          ((Item_field*) (*select_item))->field->eq(from_field)) :
         /*
           in is field of view table => check that references on translation
           table are same
         */
unknown's avatar
unknown committed
11743 11744
         ((*select_item)->type() == Item::REF_ITEM &&
          view_ref->type() == Item::REF_ITEM &&
11745 11746
          ((Item_ref *) (*select_item))->ref ==
          ((Item_ref *) view_ref)->ref)))
11747 11748 11749 11750 11751 11752 11753 11754 11755 11756 11757 11758
      /*
        If there is no such field in the FROM clause, or it is the same field as
        the one found in the SELECT clause, then use the Item created for the
        SELECT field. As a result if there was a derived field that 'shadowed'
        a table field with the same name, the table field will be chosen over
        the derived field.
      */
    {
      order->item= ref_pointer_array + counter;
      order->in_field_list=1;
      return 0;
    }
unknown's avatar
unknown committed
11759
  }
11760

unknown's avatar
unknown committed
11761
  order->in_field_list=0;
unknown's avatar
af  
unknown committed
11762
  /*
11763
    We check order_item->fixed because Item_func_group_concat can put
unknown's avatar
af  
unknown committed
11764 11765 11766 11767
    arguments for which fix_fields already was called.

    'it' reassigned in if condition because fix_field can change it.
  */
11768 11769 11770
  if (!order_item->fixed &&
      (order_item->fix_fields(thd, tables, order->item) ||
       (order_item= *order->item)->check_cols(1) ||
unknown's avatar
af  
unknown committed
11771
       thd->is_fatal_error))
11772
    return 1;					// Wrong field 
11773
  uint el= all_fields.elements;
unknown's avatar
unknown committed
11774 11775
  all_fields.push_front(order_item);		        // Add new field to field list
  ref_pointer_array[el]= order_item;
11776
  order->item= ref_pointer_array + el;
unknown's avatar
unknown committed
11777 11778 11779
  return 0;
}

11780

unknown's avatar
unknown committed
11781
/*
11782 11783
  Change order to point at item in select list. If item isn't a number
  and doesn't exits in the select list, add it the the field list.
unknown's avatar
unknown committed
11784 11785
*/

11786 11787
int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
		List<Item> &fields, List<Item> &all_fields, ORDER *order)
unknown's avatar
unknown committed
11788 11789 11790 11791
{
  thd->where="order clause";
  for (; order; order=order->next)
  {
11792
    if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
11793
			   all_fields, FALSE))
unknown's avatar
unknown committed
11794 11795 11796 11797 11798 11799
      return 1;
  }
  return 0;
}


unknown's avatar
af  
unknown committed
11800 11801 11802 11803 11804 11805 11806
/*
  Intitialize the GROUP BY list.

  SYNOPSIS
   setup_group()
   thd			Thread handler
   ref_pointer_array	We store references to all fields that was not in
unknown's avatar
unknown committed
11807
			'fields' here.
unknown's avatar
af  
unknown committed
11808 11809 11810 11811 11812 11813 11814 11815 11816 11817 11818 11819 11820 11821 11822
   fields		All fields in the select part. Any item in 'order'
			that is part of these list is replaced by a pointer
			to this fields.
   all_fields		Total list of all unique fields used by the select.
			All items in 'order' that was not part of fields will
			be added first to this list.
  order			The fields we should do GROUP BY on.
  hidden_group_fields	Pointer to flag that is set to 1 if we added any fields
			to all_fields.

  RETURN
   0  ok
   1  error (probably out of memory)
*/

unknown's avatar
unknown committed
11823
int
11824 11825 11826
setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
	    List<Item> &fields, List<Item> &all_fields, ORDER *order,
	    bool *hidden_group_fields)
unknown's avatar
unknown committed
11827 11828 11829 11830 11831
{
  *hidden_group_fields=0;
  if (!order)
    return 0;				/* Everything is ok */

11832
  if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
unknown's avatar
unknown committed
11833 11834 11835 11836 11837 11838 11839 11840 11841
  {
    Item *item;
    List_iterator<Item> li(fields);
    while ((item=li++))
      item->marker=0;			/* Marker that field is not used */
  }
  uint org_fields=all_fields.elements;

  thd->where="group statement";
11842
  for (; order; order=order->next)
unknown's avatar
unknown committed
11843
  {
11844
    if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
11845
			   all_fields, TRUE))
unknown's avatar
unknown committed
11846 11847 11848 11849
      return 1;
    (*order->item)->marker=1;		/* Mark found */
    if ((*order->item)->with_sum_func)
    {
11850
      my_error(ER_WRONG_GROUP_FIELD, MYF(0), (*order->item)->full_name());
unknown's avatar
unknown committed
11851 11852 11853
      return 1;
    }
  }
11854
  if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
unknown's avatar
unknown committed
11855 11856 11857 11858 11859 11860 11861
  {
    /* Don't allow one to use fields that is not used in GROUP BY */
    Item *item;
    List_iterator<Item> li(fields);

    while ((item=li++))
    {
11862 11863
      if (item->type() != Item::SUM_FUNC_ITEM && !item->marker &&
	  !item->const_item())
unknown's avatar
unknown committed
11864
      {
11865
	my_error(ER_WRONG_FIELD_WITH_GROUP, MYF(0), item->full_name());
unknown's avatar
unknown committed
11866 11867 11868 11869 11870 11871 11872 11873 11874 11875
	return 1;
      }
    }
  }
  if (org_fields != all_fields.elements)
    *hidden_group_fields=1;			// group fields is not used
  return 0;
}

/*
11876
  Add fields with aren't used at start of field list. Return FALSE if ok
unknown's avatar
unknown committed
11877 11878 11879 11880 11881 11882 11883 11884 11885 11886
*/

static bool
setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
		 List<Item> &all_fields, ORDER *new_field)
{
  Item	  **item;
  DBUG_ENTER("setup_new_fields");

  thd->set_query_id=1;				// Not really needed, but...
11887
  uint counter;
11888
  bool not_used;
unknown's avatar
unknown committed
11889
  for (; new_field ; new_field= new_field->next)
unknown's avatar
unknown committed
11890
  {
11891
    if ((item= find_item_in_list(*new_field->item, fields, &counter,
11892
				 IGNORE_ERRORS, &not_used)))
unknown's avatar
unknown committed
11893 11894 11895 11896
      new_field->item=item;			/* Change to shared Item */
    else
    {
      thd->where="procedure list";
unknown's avatar
unknown committed
11897
      if ((*new_field->item)->fix_fields(thd, tables, new_field->item))
unknown's avatar
unknown committed
11898 11899 11900 11901 11902 11903 11904 11905 11906
	DBUG_RETURN(1); /* purecov: inspected */
      all_fields.push_front(*new_field->item);
      new_field->item=all_fields.head_ref();
    }
  }
  DBUG_RETURN(0);
}

/*
11907 11908 11909
  Create a group by that consist of all non const fields. Try to use
  the fields in the order given by 'order' to allow one to optimize
  away 'order by'.
unknown's avatar
unknown committed
11910 11911 11912
*/

static ORDER *
11913 11914
create_distinct_group(THD *thd, ORDER *order_list, List<Item> &fields, 
		      bool *all_order_by_fields_used)
unknown's avatar
unknown committed
11915 11916 11917 11918 11919
{
  List_iterator<Item> li(fields);
  Item *item;
  ORDER *order,*group,**prev;

11920
  *all_order_by_fields_used= 1;
unknown's avatar
unknown committed
11921 11922 11923 11924 11925 11926 11927 11928
  while ((item=li++))
    item->marker=0;			/* Marker that field is not used */

  prev= &group;  group=0;
  for (order=order_list ; order; order=order->next)
  {
    if (order->in_field_list)
    {
11929
      ORDER *ord=(ORDER*) thd->memdup((char*) order,sizeof(ORDER));
unknown's avatar
unknown committed
11930 11931 11932 11933 11934 11935
      if (!ord)
	return 0;
      *prev=ord;
      prev= &ord->next;
      (*ord->item)->marker=1;
    }
11936 11937
    else
      *all_order_by_fields_used= 0;
unknown's avatar
unknown committed
11938 11939 11940 11941 11942 11943 11944 11945 11946
  }

  li.rewind();
  while ((item=li++))
  {
    if (item->const_item() || item->with_sum_func)
      continue;
    if (!item->marker)
    {
11947
      ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER));
unknown's avatar
unknown committed
11948 11949 11950 11951 11952 11953 11954 11955 11956 11957 11958 11959 11960 11961
      if (!ord)
	return 0;
      ord->item=li.ref();
      ord->asc=1;
      *prev=ord;
      prev= &ord->next;
    }
  }
  *prev=0;
  return group;
}


/*****************************************************************************
11962
  Update join with count of the different type of fields
unknown's avatar
unknown committed
11963 11964 11965
*****************************************************************************/

void
unknown's avatar
unknown committed
11966 11967
count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
		  bool reset_with_sum_func)
unknown's avatar
unknown committed
11968 11969 11970 11971
{
  List_iterator<Item> li(fields);
  Item *field;

11972
  param->field_count=param->sum_func_count=param->func_count=
unknown's avatar
unknown committed
11973
    param->hidden_field_count=0;
unknown's avatar
unknown committed
11974 11975 11976 11977 11978 11979 11980 11981 11982 11983 11984 11985 11986 11987 11988 11989 11990 11991 11992 11993 11994 11995 11996 11997 11998
  param->quick_group=1;
  while ((field=li++))
  {
    Item::Type type=field->type();
    if (type == Item::FIELD_ITEM)
      param->field_count++;
    else if (type == Item::SUM_FUNC_ITEM)
    {
      if (! field->const_item())
      {
	Item_sum *sum_item=(Item_sum*) field;
	if (!sum_item->quick_group)
	  param->quick_group=0;			// UDF SUM function
	param->sum_func_count++;

	for (uint i=0 ; i < sum_item->arg_count ; i++)
	{
	  if (sum_item->args[0]->type() == Item::FIELD_ITEM)
	    param->field_count++;
	  else
	    param->func_count++;
	}
      }
    }
    else
unknown's avatar
unknown committed
11999
    {
unknown's avatar
unknown committed
12000
      param->func_count++;
unknown's avatar
unknown committed
12001 12002 12003
      if (reset_with_sum_func)
	field->with_sum_func=0;
    }
unknown's avatar
unknown committed
12004 12005 12006 12007 12008 12009 12010 12011 12012 12013 12014 12015 12016 12017 12018
  }
}


/*
  Return 1 if second is a subpart of first argument
  If first parts has different direction, change it to second part
  (group is sorted like order)
*/

static bool
test_if_subpart(ORDER *a,ORDER *b)
{
  for (; a && b; a=a->next,b=b->next)
  {
12019
    if ((*a->item)->eq(*b->item,1))
unknown's avatar
unknown committed
12020 12021 12022 12023 12024 12025 12026 12027 12028 12029 12030 12031 12032 12033 12034 12035 12036 12037 12038 12039 12040 12041 12042 12043 12044 12045
      a->asc=b->asc;
    else
      return 0;
  }
  return test(!b);
}

/*
  Return table number if there is only one table in sort order
  and group and order is compatible
  else return 0;
*/

static TABLE *
get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables)
{
  table_map map= (table_map) 0;
  DBUG_ENTER("get_sort_by_table");

  if (!a)
    a=b;					// Only one need to be given
  else if (!b)
    b=a;

  for (; a && b; a=a->next,b=b->next)
  {
12046
    if (!(*a->item)->eq(*b->item,1))
unknown's avatar
unknown committed
12047 12048 12049
      DBUG_RETURN(0);
    map|=a->item[0]->used_tables();
  }
unknown's avatar
unknown committed
12050
  if (!map || (map & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT)))
unknown's avatar
unknown committed
12051 12052
    DBUG_RETURN(0);

12053
  for (; !(map & tables->table->map); tables= tables->next_leaf);
unknown's avatar
unknown committed
12054 12055 12056 12057 12058 12059 12060 12061 12062 12063 12064 12065
  if (map != tables->table->map)
    DBUG_RETURN(0);				// More than one table
  DBUG_PRINT("exit",("sort by table: %d",tables->table->tablenr));
  DBUG_RETURN(tables->table);
}


	/* calc how big buffer we need for comparing group entries */

static void
calc_group_buffer(JOIN *join,ORDER *group)
{
12066 12067
  uint key_length=0, parts=0, null_parts=0;

unknown's avatar
unknown committed
12068 12069 12070 12071
  if (group)
    join->group= 1;
  for (; group ; group=group->next)
  {
12072 12073
    Item *group_item= *group->item;
    Field *field= group_item->get_tmp_table_field();
unknown's avatar
unknown committed
12074 12075 12076 12077
    if (field)
    {
      if (field->type() == FIELD_TYPE_BLOB)
	key_length+=MAX_BLOB_WIDTH;		// Can't be used as a key
12078 12079
      else if (field->type() == MYSQL_TYPE_VARCHAR)
        key_length+= field->field_length + HA_KEY_BLOB_LENGTH;
unknown's avatar
unknown committed
12080
      else
12081
	key_length+= field->pack_length();
unknown's avatar
unknown committed
12082 12083
    }
    else
12084 12085 12086 12087 12088 12089 12090 12091 12092 12093 12094 12095 12096 12097 12098 12099 12100 12101 12102 12103 12104 12105 12106 12107 12108 12109
    { 
      switch (group_item->result_type()) {
      case REAL_RESULT:
        key_length+= sizeof(double);
        break;
      case INT_RESULT:
        key_length+= sizeof(longlong);
        break;
      case DECIMAL_RESULT:
        key_length+= my_decimal_get_binary_size(group_item->max_length - 
                                                (group_item->decimals ? 1 : 0),
                                                group_item->decimals);
        break;
      case STRING_RESULT:
        /*
          Group strings are taken as varstrings and require an length field.
          A field is not yet created by create_tmp_field()
          and the sizes should match up.
        */
        key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH;
        break;
      default:
        /* This case should never be choosen */
        DBUG_ASSERT(0);
        join->thd->fatal_error();
      }
12110
    }
unknown's avatar
unknown committed
12111
    parts++;
12112
    if (group_item->maybe_null)
12113
      null_parts++;
unknown's avatar
unknown committed
12114
  }
12115
  join->tmp_table_param.group_length=key_length+null_parts;
unknown's avatar
unknown committed
12116
  join->tmp_table_param.group_parts=parts;
12117
  join->tmp_table_param.group_null_parts=null_parts;
unknown's avatar
unknown committed
12118 12119
}

12120

12121
/*
12122
  allocate group fields or take prepared (cached)
12123

12124
  SYNOPSIS
12125 12126 12127 12128 12129 12130 12131 12132 12133 12134 12135 12136
    make_group_fields()
    main_join - join of current select
    curr_join - current join (join of current select or temporary copy of it)

  RETURN
    0 - ok
    1 - failed
*/

static bool
make_group_fields(JOIN *main_join, JOIN *curr_join)
{
12137 12138 12139 12140 12141 12142 12143 12144 12145 12146 12147 12148
  if (main_join->group_fields_cache.elements)
  {
    curr_join->group_fields= main_join->group_fields_cache;
    curr_join->sort_and_group= 1;
  }
  else
  {
    if (alloc_group_fields(curr_join, curr_join->group_list))
      return (1);
    main_join->group_fields_cache= curr_join->group_fields;
  }
  return (0);
12149
}
unknown's avatar
unknown committed
12150

12151

unknown's avatar
unknown committed
12152
/*
12153 12154
  Get a list of buffers for saveing last group
  Groups are saved in reverse order for easyer check loop
unknown's avatar
unknown committed
12155 12156 12157 12158 12159 12160 12161 12162 12163 12164 12165 12166 12167 12168 12169 12170 12171 12172 12173 12174 12175 12176
*/

static bool
alloc_group_fields(JOIN *join,ORDER *group)
{
  if (group)
  {
    for (; group ; group=group->next)
    {
      Item_buff *tmp=new_Item_buff(*group->item);
      if (!tmp || join->group_fields.push_front(tmp))
	return TRUE;
    }
  }
  join->sort_and_group=1;			/* Mark for do_select */
  return FALSE;
}


static int
test_if_group_changed(List<Item_buff> &list)
{
12177
  DBUG_ENTER("test_if_group_changed");
unknown's avatar
unknown committed
12178 12179 12180 12181 12182 12183 12184 12185 12186
  List_iterator<Item_buff> li(list);
  int idx= -1,i;
  Item_buff *buff;

  for (i=(int) list.elements-1 ; (buff=li++) ; i--)
  {
    if (buff->cmp())
      idx=i;
  }
12187 12188
  DBUG_PRINT("info", ("idx: %d", idx));
  DBUG_RETURN(idx);
unknown's avatar
unknown committed
12189 12190 12191 12192
}


/*
12193
  Setup copy_fields to save fields at start of new group
unknown's avatar
unknown committed
12194 12195 12196 12197 12198 12199 12200 12201 12202 12203 12204 12205 12206 12207 12208 12209 12210 12211 12212

  setup_copy_fields()
    thd - THD pointer
    param - temporary table parameters
    ref_pointer_array - array of pointers to top elements of filed list
    res_selected_fields - new list of items of select item list
    res_all_fields - new list of all items
    elements - number of elements in select item list
    all_fields - all fields list

  DESCRIPTION
    Setup copy_fields to save fields at start of new group
    Only FIELD_ITEM:s and FUNC_ITEM:s needs to be saved between groups.
    Change old item_field to use a new field with points at saved fieldvalue
    This function is only called before use of send_fields
  
  RETURN
    0 - ok
    !=0 - error
unknown's avatar
unknown committed
12213 12214 12215
*/

bool
12216 12217
setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
		  Item **ref_pointer_array,
unknown's avatar
unknown committed
12218 12219
		  List<Item> &res_selected_fields, List<Item> &res_all_fields,
		  uint elements, List<Item> &all_fields)
unknown's avatar
unknown committed
12220 12221
{
  Item *pos;
unknown's avatar
unknown committed
12222
  List_iterator_fast<Item> li(all_fields);
unknown's avatar
unknown committed
12223
  Copy_field *copy;
unknown's avatar
unknown committed
12224 12225 12226
  res_selected_fields.empty();
  res_all_fields.empty();
  List_iterator_fast<Item> itr(res_all_fields);
12227
  List<Item> extra_funcs;
unknown's avatar
unknown committed
12228
  uint i, border= all_fields.elements - elements;
unknown's avatar
af  
unknown committed
12229
  DBUG_ENTER("setup_copy_fields");
unknown's avatar
unknown committed
12230 12231

  if (!(copy=param->copy_field= new Copy_field[param->field_count]))
12232
    goto err2;
unknown's avatar
unknown committed
12233 12234

  param->copy_funcs.empty();
12235
  for (i= 0; (pos= li++); i++)
unknown's avatar
unknown committed
12236 12237 12238
  {
    if (pos->type() == Item::FIELD_ITEM)
    {
12239
      Item_field *item;
unknown's avatar
af  
unknown committed
12240
      if (!(item= new Item_field(thd, ((Item_field*) pos))))
12241 12242
	goto err;
      pos= item;
unknown's avatar
unknown committed
12243 12244
      if (item->field->flags & BLOB_FLAG)
      {
12245
	if (!(pos= new Item_copy_string(pos)))
unknown's avatar
unknown committed
12246
	  goto err;
12247 12248 12249 12250 12251 12252 12253 12254 12255 12256
       /*
         Item_copy_string::copy for function can call 
         Item_copy_string::val_int for blob via Item_ref.
         But if Item_copy_string::copy for blob isn't called before,
         it's value will be wrong
         so let's insert Item_copy_string for blobs in the beginning of 
         copy_funcs
         (to see full test case look at having.test, BUG #4358) 
       */
	if (param->copy_funcs.push_front(pos))
unknown's avatar
unknown committed
12257 12258
	  goto err;
      }
12259 12260 12261 12262 12263 12264 12265
      else
      {
	/* 
	   set up save buffer and change result_field to point at 
	   saved value
	*/
	Field *field= item->field;
unknown's avatar
unknown committed
12266
	item->result_field=field->new_field(thd->mem_root,field->table);
12267 12268 12269 12270 12271 12272 12273
	char *tmp=(char*) sql_alloc(field->pack_length()+1);
	if (!tmp)
	  goto err;
	copy->set(tmp, item->result_field);
	item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1);
	copy++;
      }
unknown's avatar
unknown committed
12274 12275
    }
    else if ((pos->type() == Item::FUNC_ITEM ||
12276 12277
	      pos->type() == Item::SUBSELECT_ITEM ||
	      pos->type() == Item::CACHE_ITEM ||
unknown's avatar
unknown committed
12278 12279 12280 12281 12282 12283 12284 12285 12286 12287 12288
	      pos->type() == Item::COND_ITEM) &&
	     !pos->with_sum_func)
    {						// Save for send fields
      /* TODO:
	 In most cases this result will be sent to the user.
	 This should be changed to use copy_int or copy_real depending
	 on how the value is to be used: In some cases this may be an
	 argument in a group function, like: IF(ISNULL(col),0,COUNT(*))
      */
      if (!(pos=new Item_copy_string(pos)))
	goto err;
12289 12290 12291 12292 12293 12294
      if (i < border)                           // HAVING, ORDER and GROUP BY
      {
        if (extra_funcs.push_back(pos))
          goto err;
      }
      else if (param->copy_funcs.push_back(pos))
unknown's avatar
unknown committed
12295 12296
	goto err;
    }
unknown's avatar
unknown committed
12297 12298
    res_all_fields.push_back(pos);
    ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
12299
      pos;
unknown's avatar
unknown committed
12300
  }
unknown's avatar
unknown committed
12301
  param->copy_field_end= copy;
12302 12303 12304

  for (i= 0; i < border; i++)
    itr++;
unknown's avatar
unknown committed
12305
  itr.sublist(res_selected_fields, elements);
12306 12307 12308 12309 12310 12311
  /*
    Put elements from HAVING, ORDER BY and GROUP BY last to ensure that any
    reference used in these will resolve to a item that is already calculated
  */
  param->copy_funcs.concat(&extra_funcs);

unknown's avatar
unknown committed
12312 12313 12314
  DBUG_RETURN(0);

 err:
12315
  delete [] param->copy_field;			// This is never 0
unknown's avatar
unknown committed
12316
  param->copy_field=0;
12317
err2:
unknown's avatar
unknown committed
12318 12319 12320 12321 12322
  DBUG_RETURN(TRUE);
}


/*
12323 12324 12325 12326
  Make a copy of all simple SELECT'ed items

  This is done at the start of a new group so that we can retrieve
  these later when the group changes.
unknown's avatar
unknown committed
12327 12328 12329 12330 12331 12332
*/

void
copy_fields(TMP_TABLE_PARAM *param)
{
  Copy_field *ptr=param->copy_field;
unknown's avatar
unknown committed
12333
  Copy_field *end=param->copy_field_end;
unknown's avatar
unknown committed
12334

12335
  for (; ptr != end; ptr++)
unknown's avatar
unknown committed
12336 12337
    (*ptr->do_copy)(ptr);

unknown's avatar
unknown committed
12338
  List_iterator_fast<Item> it(param->copy_funcs);
unknown's avatar
unknown committed
12339 12340 12341 12342 12343 12344
  Item_copy_string *item;
  while ((item = (Item_copy_string*) it++))
    item->copy();
}


12345 12346
/*
  Make an array of pointers to sum_functions to speed up sum_func calculation
unknown's avatar
unknown committed
12347

12348 12349 12350 12351 12352 12353 12354 12355 12356
  SYNOPSIS
    alloc_func_list()

  RETURN
    0	ok
    1	Error
*/

bool JOIN::alloc_func_list()
unknown's avatar
unknown committed
12357
{
12358 12359 12360 12361 12362 12363 12364 12365 12366 12367 12368 12369 12370 12371 12372 12373 12374 12375 12376 12377 12378 12379 12380 12381 12382 12383 12384
  uint func_count, group_parts;
  DBUG_ENTER("alloc_func_list");

  func_count= tmp_table_param.sum_func_count;
  /*
    If we are using rollup, we need a copy of the summary functions for
    each level
  */
  if (rollup.state != ROLLUP::STATE_NONE)
    func_count*= (send_group_parts+1);

  group_parts= send_group_parts;
  /*
    If distinct, reserve memory for possible
    disctinct->group_by optimization
  */
  if (select_distinct)
    group_parts+= fields_list.elements;

  /* This must use calloc() as rollup_make_fields depends on this */
  sum_funcs= (Item_sum**) thd->calloc(sizeof(Item_sum**) * (func_count+1) +
				      sizeof(Item_sum***) * (group_parts+1));
  sum_funcs_end= (Item_sum***) (sum_funcs+func_count+1);
  DBUG_RETURN(sum_funcs == 0);
}


unknown's avatar
af  
unknown committed
12385 12386 12387 12388 12389 12390 12391 12392
/*
  Initialize 'sum_funcs' array with all Item_sum objects

  SYNOPSIS
    make_sum_func_list()
    field_list		All items
    send_fields		Items in select list
    before_group_by	Set to 1 if this is called before GROUP BY handling
12393
    recompute           Set to TRUE if sum_funcs must be recomputed
unknown's avatar
af  
unknown committed
12394 12395 12396 12397 12398 12399

  RETURN
    0  ok
    1  error
*/

12400
bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
12401
			      bool before_group_by, bool recompute)
unknown's avatar
unknown committed
12402
{
12403
  List_iterator_fast<Item> it(field_list);
12404 12405
  Item_sum **func;
  Item *item;
unknown's avatar
unknown committed
12406 12407
  DBUG_ENTER("make_sum_func_list");

12408 12409 12410
  if (*sum_funcs && !recompute)
    DBUG_RETURN(FALSE); /* We have already initialized sum_funcs. */

12411 12412
  func= sum_funcs;
  while ((item=it++))
unknown's avatar
unknown committed
12413
  {
12414 12415
    if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
      *func++= (Item_sum*) item;
unknown's avatar
unknown committed
12416
  }
12417 12418 12419
  if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
  {
    rollup.state= ROLLUP::STATE_READY;
12420
    if (rollup_make_fields(field_list, send_fields, &func))
12421 12422 12423 12424 12425 12426 12427
      DBUG_RETURN(TRUE);			// Should never happen
  }
  else if (rollup.state == ROLLUP::STATE_NONE)
  {
    for (uint i=0 ; i <= send_group_parts ;i++)
      sum_funcs_end[i]= func;
  }
unknown's avatar
unknown committed
12428 12429 12430 12431 12432 12433
  *func=0;					// End marker
  DBUG_RETURN(FALSE);
}


/*
unknown's avatar
af  
unknown committed
12434
  Change all funcs and sum_funcs to fields in tmp table, and create
unknown's avatar
unknown committed
12435 12436 12437 12438 12439 12440 12441 12442 12443 12444 12445 12446 12447
  new list of all items.

  change_to_use_tmp_fields()
    thd - THD pointer
    ref_pointer_array - array of pointers to top elements of filed list
    res_selected_fields - new list of items of select item list
    res_all_fields - new list of all items
    elements - number of elements in select item list
    all_fields - all fields list

   RETURN
    0 - ok
    !=0 - error
unknown's avatar
unknown committed
12448 12449 12450
*/

static bool
12451
change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
unknown's avatar
unknown committed
12452 12453 12454
			 List<Item> &res_selected_fields,
			 List<Item> &res_all_fields,
			 uint elements, List<Item> &all_fields)
unknown's avatar
unknown committed
12455
{
unknown's avatar
unknown committed
12456
  List_iterator_fast<Item> it(all_fields);
unknown's avatar
unknown committed
12457
  Item *item_field,*item;
unknown's avatar
unknown committed
12458 12459
  DBUG_ENTER("change_to_use_tmp_fields");

unknown's avatar
unknown committed
12460 12461
  res_selected_fields.empty();
  res_all_fields.empty();
unknown's avatar
unknown committed
12462

unknown's avatar
unknown committed
12463
  uint i, border= all_fields.elements - elements;
12464
  for (i= 0; (item= it++); i++)
unknown's avatar
unknown committed
12465 12466
  {
    Field *field;
12467
    
unknown's avatar
unknown committed
12468
    if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
12469 12470
      item_field= item;
    else
unknown's avatar
unknown committed
12471
    {
12472
      if (item->type() == Item::FIELD_ITEM)
unknown's avatar
unknown committed
12473
      {
12474
	item_field= item->get_tmp_table_item(thd);
unknown's avatar
unknown committed
12475
      }
12476
      else if ((field= item->get_tmp_table_field()))
12477 12478 12479 12480 12481 12482
      {
	if (item->type() == Item::SUM_FUNC_ITEM && field->table->group)
	  item_field= ((Item_sum*) item)->result_item(field);
	else
	  item_field= (Item*) new Item_field(field);
	if (!item_field)
unknown's avatar
unknown committed
12483 12484
	  DBUG_RETURN(TRUE);                    // Fatal error
	item_field->name= item->name;
12485 12486 12487 12488
#ifndef DBUG_OFF
	if (_db_on_ && !item_field->name)
	{
	  char buff[256];
12489
	  String str(buff,sizeof(buff),&my_charset_bin);
12490 12491 12492 12493
	  str.length(0);
	  item->print(&str);
	  item_field->name= sql_strmake(str.ptr(),str.length());
	}
unknown's avatar
unknown committed
12494
#endif
12495 12496 12497
      }
      else
	item_field= item;
unknown's avatar
unknown committed
12498 12499 12500
    }
    res_all_fields.push_back(item_field);
    ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
12501
      item_field;
unknown's avatar
unknown committed
12502
  }
12503

unknown's avatar
unknown committed
12504
  List_iterator_fast<Item> itr(res_all_fields);
12505 12506
  for (i= 0; i < border; i++)
    itr++;
unknown's avatar
unknown committed
12507
  itr.sublist(res_selected_fields, elements);
unknown's avatar
unknown committed
12508
  DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
12509 12510 12511 12512
}


/*
12513 12514
  Change all sum_func refs to fields to point at fields in tmp table
  Change all funcs to be fields in tmp table
unknown's avatar
unknown committed
12515 12516 12517 12518 12519 12520 12521 12522 12523 12524

  change_refs_to_tmp_fields()
    thd - THD pointer
    ref_pointer_array - array of pointers to top elements of filed list
    res_selected_fields - new list of items of select item list
    res_all_fields - new list of all items
    elements - number of elements in select item list
    all_fields - all fields list

   RETURN
12525 12526
    0	ok
    1	error
unknown's avatar
unknown committed
12527 12528 12529
*/

static bool
12530
change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
unknown's avatar
unknown committed
12531 12532 12533
			  List<Item> &res_selected_fields,
			  List<Item> &res_all_fields, uint elements,
			  List<Item> &all_fields)
unknown's avatar
unknown committed
12534
{
unknown's avatar
unknown committed
12535
  List_iterator_fast<Item> it(all_fields);
12536
  Item *item, *new_item;
unknown's avatar
unknown committed
12537 12538
  res_selected_fields.empty();
  res_all_fields.empty();
unknown's avatar
unknown committed
12539

unknown's avatar
unknown committed
12540
  uint i, border= all_fields.elements - elements;
12541
  for (i= 0; (item= it++); i++)
unknown's avatar
unknown committed
12542
  {
unknown's avatar
unknown committed
12543 12544
    res_all_fields.push_back(new_item= item->get_tmp_table_item(thd));
    ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
12545
      new_item;
unknown's avatar
unknown committed
12546
  }
12547

unknown's avatar
unknown committed
12548
  List_iterator_fast<Item> itr(res_all_fields);
12549 12550
  for (i= 0; i < border; i++)
    itr++;
unknown's avatar
unknown committed
12551
  itr.sublist(res_selected_fields, elements);
12552

12553
  return thd->is_fatal_error;
unknown's avatar
unknown committed
12554 12555 12556 12557 12558
}



/******************************************************************************
12559
  Code for calculating functions
unknown's avatar
unknown committed
12560 12561
******************************************************************************/

12562 12563 12564 12565 12566 12567 12568 12569 12570 12571 12572 12573 12574 12575 12576 12577 12578

/*
  Call ::setup for all sum functions

  SYNOPSIS
    setup_sum_funcs()
    thd           thread handler
    func_ptr      sum function list

  RETURN
    FALSE  ok
    TRUE   error
*/

static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr)
{
  Item_sum *func;
unknown's avatar
unknown committed
12579
  DBUG_ENTER("setup_sum_funcs");
12580 12581
  while ((func= *(func_ptr++)))
    if (func->setup(thd))
unknown's avatar
unknown committed
12582 12583
      DBUG_RETURN(TRUE);
  DBUG_RETURN(FALSE);
12584 12585 12586
}


unknown's avatar
unknown committed
12587 12588 12589 12590 12591 12592 12593 12594 12595 12596 12597 12598 12599 12600 12601 12602 12603
static void
init_tmptable_sum_functions(Item_sum **func_ptr)
{
  Item_sum *func;
  while ((func= *(func_ptr++)))
    func->reset_field();
}


	/* Update record 0 in tmp_table from record 1 */

static void
update_tmptable_sum_func(Item_sum **func_ptr,
			 TABLE *tmp_table __attribute__((unused)))
{
  Item_sum *func;
  while ((func= *(func_ptr++)))
unknown's avatar
unknown committed
12604
    func->update_field();
unknown's avatar
unknown committed
12605 12606 12607 12608 12609 12610
}


	/* Copy result of sum functions to record in tmp_table */

static void
unknown's avatar
unknown committed
12611
copy_sum_funcs(Item_sum **func_ptr, Item_sum **end_ptr)
unknown's avatar
unknown committed
12612
{
unknown's avatar
unknown committed
12613 12614
  for (; func_ptr != end_ptr ; func_ptr++)
    (void) (*func_ptr)->save_in_result_field(1);
unknown's avatar
unknown committed
12615 12616 12617 12618
  return;
}


12619 12620
static bool
init_sum_functions(Item_sum **func_ptr, Item_sum **end_ptr)
unknown's avatar
unknown committed
12621
{
12622 12623 12624 12625 12626 12627 12628 12629 12630 12631 12632 12633
  for (; func_ptr != end_ptr ;func_ptr++)
  {
    if ((*func_ptr)->reset())
      return 1;
  }
  /* If rollup, calculate the upper sum levels */
  for ( ; *func_ptr ; func_ptr++)
  {
    if ((*func_ptr)->add())
      return 1;
  }
  return 0;
unknown's avatar
unknown committed
12634 12635 12636 12637 12638 12639 12640 12641 12642 12643 12644 12645 12646 12647 12648 12649
}


static bool
update_sum_func(Item_sum **func_ptr)
{
  Item_sum *func;
  for (; (func= (Item_sum*) *func_ptr) ; func_ptr++)
    if (func->add())
      return 1;
  return 0;
}

	/* Copy result of functions to record in tmp_table */

void
unknown's avatar
unknown committed
12650
copy_funcs(Item **func_ptr)
unknown's avatar
unknown committed
12651
{
unknown's avatar
unknown committed
12652
  Item *func;
unknown's avatar
unknown committed
12653
  for (; (func = *func_ptr) ; func_ptr++)
unknown's avatar
unknown committed
12654
    func->save_in_result_field(1);
unknown's avatar
unknown committed
12655 12656 12657
}


12658
/*
12659 12660
  Create a condition for a const reference and add this to the
  currenct select for the table
12661
*/
unknown's avatar
unknown committed
12662 12663 12664 12665 12666 12667 12668 12669 12670 12671 12672 12673 12674 12675 12676

static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
{
  DBUG_ENTER("add_ref_to_table_cond");
  if (!join_tab->ref.key_parts)
    DBUG_RETURN(FALSE);

  Item_cond_and *cond=new Item_cond_and();
  TABLE *table=join_tab->table;
  int error;
  if (!cond)
    DBUG_RETURN(TRUE);

  for (uint i=0 ; i < join_tab->ref.key_parts ; i++)
  {
12677 12678
    Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i].
			      fieldnr-1];
unknown's avatar
unknown committed
12679
    Item *value=join_tab->ref.items[i];
unknown's avatar
af  
unknown committed
12680
    cond->add(new Item_func_equal(new Item_field(field), value));
unknown's avatar
unknown committed
12681
  }
12682
  if (thd->is_fatal_error)
unknown's avatar
unknown committed
12683
    DBUG_RETURN(TRUE);
12684

unknown's avatar
unknown committed
12685 12686
  if (!cond->fixed)
    cond->fix_fields(thd,(TABLE_LIST *) 0, (Item**)&cond);
unknown's avatar
unknown committed
12687 12688 12689 12690 12691
  if (join_tab->select)
  {
    error=(int) cond->add(join_tab->select->cond);
    join_tab->select_cond=join_tab->select->cond=cond;
  }
unknown's avatar
unknown committed
12692 12693
  else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0,
                                          &error)))
unknown's avatar
unknown committed
12694 12695 12696 12697 12698
    join_tab->select_cond=cond;

  DBUG_RETURN(error ? TRUE : FALSE);
}

12699 12700 12701 12702 12703 12704 12705 12706 12707 12708 12709 12710 12711 12712 12713 12714 12715

/*
  Free joins of subselect of this select.

  free_underlaid_joins()
    thd - THD pointer
    select - pointer to st_select_lex which subselects joins we will free
*/

void free_underlaid_joins(THD *thd, SELECT_LEX *select)
{
  for (SELECT_LEX_UNIT *unit= select->first_inner_unit();
       unit;
       unit= unit->next_unit())
    unit->cleanup();
}

unknown's avatar
unknown committed
12716
/****************************************************************************
12717 12718 12719 12720 12721 12722 12723 12724 12725 12726 12727 12728 12729 12730 12731 12732 12733 12734 12735
  ROLLUP handling
****************************************************************************/

/* Allocate memory needed for other rollup functions */

bool JOIN::rollup_init()
{
  uint i,j;
  Item **ref_array;

  tmp_table_param.quick_group= 0;	// Can't create groups in tmp table
  rollup.state= ROLLUP::STATE_INITED;

  /*
    Create pointers to the different sum function groups
    These are updated by rollup_make_fields()
  */
  tmp_table_param.group_parts= send_group_parts;

unknown's avatar
unknown committed
12736 12737 12738 12739 12740
  if (!(rollup.null_items= (Item_null_result**) thd->alloc((sizeof(Item*) +
                                                sizeof(Item**) +
                                                sizeof(List<Item>) +
				                ref_pointer_array_size)
				                * send_group_parts )))
12741
    return 1;
unknown's avatar
unknown committed
12742 12743
  
  rollup.fields= (List<Item>*) (rollup.null_items + send_group_parts);
12744 12745 12746 12747 12748 12749 12750 12751 12752
  rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
  ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts);

  /*
    Prepare space for field list for the different levels
    These will be filled up in rollup_make_fields()
  */
  for (i= 0 ; i < send_group_parts ; i++)
  {
unknown's avatar
unknown committed
12753
    rollup.null_items[i]= new (thd->mem_root) Item_null_result();
12754 12755
    List<Item> *rollup_fields= &rollup.fields[i];
    rollup_fields->empty();
12756 12757
    rollup.ref_pointer_arrays[i]= ref_array;
    ref_array+= all_fields.elements;
unknown's avatar
unknown committed
12758 12759 12760
  }
  for (i= 0 ; i < send_group_parts; i++)
  {
12761
    for (j=0 ; j < fields_list.elements ; j++)
unknown's avatar
unknown committed
12762
      rollup.fields[i].push_back(rollup.null_items[i]);
12763
  }
unknown's avatar
unknown committed
12764 12765 12766 12767 12768 12769 12770 12771 12772 12773 12774
  List_iterator_fast<Item> it(fields_list);
  Item *item;
  while ((item= it++))
  {
    ORDER *group_tmp;
    for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
    {
      if (*group_tmp->item == item)
        item->maybe_null= 1;
    }
  }
12775
  return 0;
unknown's avatar
unknown committed
12776

12777 12778 12779 12780 12781 12782 12783 12784
}
  

/*
  Fill up rollup structures with pointers to fields to use

  SYNOPSIS
    rollup_make_fields()
12785 12786
    fields_arg			List of all fields (hidden and real ones)
    sel_fields			Pointer to selected fields
12787 12788 12789 12790 12791 12792 12793 12794 12795 12796 12797
    func			Store here a pointer to all fields

  IMPLEMENTATION:
    Creates copies of item_sum items for each sum level

  RETURN
    0	if ok
	In this case func is pointing to next not used element.
    1   on error
*/

12798
bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields,
12799 12800
			      Item_sum ***func)
{
12801 12802
  List_iterator_fast<Item> it(fields_arg);
  Item *first_field= sel_fields.head();
12803 12804 12805 12806 12807 12808 12809 12810 12811 12812 12813 12814 12815 12816 12817 12818 12819 12820 12821 12822 12823 12824 12825
  uint level;

  /*
    Create field lists for the different levels

    The idea here is to have a separate field list for each rollup level to
    avoid all runtime checks of which columns should be NULL.

    The list is stored in reverse order to get sum function in such an order
    in func that it makes it easy to reset them with init_sum_functions()

    Assuming:  SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP

    rollup.fields[0] will contain list where a,b,c is NULL
    rollup.fields[1] will contain list where b,c is NULL
    ...
    rollup.ref_pointer_array[#] points to fields for rollup.fields[#]
    ...
    sum_funcs_end[0] points to all sum functions
    sum_funcs_end[1] points to all sum functions, except grand totals
    ...
  */

12826
  for (level=0 ; level < send_group_parts ; level++)
12827 12828 12829 12830 12831 12832 12833 12834 12835 12836
  {
    uint i;
    uint pos= send_group_parts - level -1;
    bool real_fields= 0;
    Item *item;
    List_iterator<Item> new_it(rollup.fields[pos]);
    Item **ref_array_start= rollup.ref_pointer_arrays[pos];
    ORDER *start_group;

    /* Point to first hidden field */
12837
    Item **ref_array= ref_array_start + fields_arg.elements-1;
12838 12839 12840 12841 12842 12843 12844 12845 12846 12847 12848 12849 12850 12851 12852 12853 12854 12855 12856 12857 12858 12859 12860 12861 12862 12863 12864 12865 12866 12867 12868 12869 12870 12871 12872 12873 12874 12875 12876

    /* Remember where the sum functions ends for the previous level */
    sum_funcs_end[pos+1]= *func;

    /* Find the start of the group for this level */
    for (i= 0, start_group= group_list ;
	 i++ < pos ;
	 start_group= start_group->next)
      ;

    it.rewind();
    while ((item= it++))
    {
      if (item == first_field)
      {
	real_fields= 1;				// End of hidden fields
	ref_array= ref_array_start;
      }

      if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
      {
	/*
	  This is a top level summary function that must be replaced with
	  a sum function that is reset for this level.

	  NOTE: This code creates an object which is not that nice in a
	  sub select.  Fortunately it's not common to have rollup in
	  sub selects.
	*/
	item= item->copy_or_same(thd);
	((Item_sum*) item)->make_unique();
	if (((Item_sum*) item)->setup(thd))
	  return 1;
	*(*func)= (Item_sum*) item;
	(*func)++;
      }
      else if (real_fields)
      {
	/* Check if this is something that is part of this group by */
12877
	ORDER *group_tmp;
unknown's avatar
unknown committed
12878
	for (group_tmp= start_group, i= pos ;
unknown's avatar
unknown committed
12879
             group_tmp ; group_tmp= group_tmp->next, i++)
12880
	{
12881
	  if (*group_tmp->item == item)
12882
	  {
unknown's avatar
unknown committed
12883
            Item_null_result *null_item;
12884 12885 12886 12887 12888
	    /*
	      This is an element that is used by the GROUP BY and should be
	      set to NULL in this level
	    */
	    item->maybe_null= 1;		// Value will be null sometimes
unknown's avatar
unknown committed
12889 12890 12891 12892
            null_item= rollup.null_items[i];
            DBUG_ASSERT(null_item->result_field == 0 ||
                        null_item->result_field ==
                        ((Item_field *) item)->result_field);
unknown's avatar
unknown committed
12893 12894
            null_item->result_field= ((Item_field *) item)->result_field;
            item= null_item;
12895 12896 12897 12898 12899 12900 12901 12902 12903 12904 12905 12906 12907 12908 12909 12910 12911 12912 12913 12914 12915 12916 12917 12918 12919 12920 12921 12922 12923 12924 12925 12926 12927 12928 12929 12930 12931 12932 12933 12934 12935 12936 12937 12938 12939 12940 12941 12942
	    break;
	  }
	}
      }
      *ref_array= item;
      if (real_fields)
      {
	(void) new_it++;			// Point to next item
	new_it.replace(item);			// Replace previous
	ref_array++;
      }
      else
	ref_array--;
    }
  }
  sum_funcs_end[0]= *func;			// Point to last function
  return 0;
}

/*
  Send all rollup levels higher than the current one to the client

  SYNOPSIS:
    rollup_send_data()
    idx			Level we are on:
			0 = Total sum level
			1 = First group changed  (a)
			2 = Second group changed (a,b)

  SAMPLE
    SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP

  RETURN
    0	ok
    1   If send_data_failed()
*/

int JOIN::rollup_send_data(uint idx)
{
  uint i;
  for (i= send_group_parts ; i-- > idx ; )
  {
    /* Get reference pointers to sum functions in place */
    memcpy((char*) ref_pointer_array,
	   (char*) rollup.ref_pointer_arrays[i],
	   ref_pointer_array_size);
    if ((!having || having->val_int()))
    {
unknown's avatar
unknown committed
12943
      if (send_records < unit->select_limit_cnt && do_send_rows &&
12944 12945 12946 12947 12948 12949 12950 12951 12952 12953
	  result->send_data(rollup.fields[i]))
	return 1;
      send_records++;
    }
  }
  /* Restore ref_pointer_array */
  set_items_ref_array(current_ref_pointer_array);
  return 0;
}

unknown's avatar
unknown committed
12954 12955 12956 12957 12958 12959 12960 12961 12962 12963 12964 12965 12966 12967 12968 12969 12970 12971 12972 12973 12974 12975 12976 12977 12978 12979 12980 12981 12982 12983 12984 12985 12986 12987 12988 12989 12990 12991 12992 12993 12994 12995 12996 12997 12998 12999 13000 13001 13002 13003 13004 13005
/*
  Write all rollup levels higher than the current one to a temp table

  SYNOPSIS:
    rollup_write_data()
    idx                 Level we are on:
                        0 = Total sum level
                        1 = First group changed  (a)
                        2 = Second group changed (a,b)
    table               reference to temp table

  SAMPLE
    SELECT a, b, SUM(c) FROM t1 GROUP BY a,b WITH ROLLUP

  RETURN
    0	ok
    1   if write_data_failed()
*/

int JOIN::rollup_write_data(uint idx, TABLE *table)
{
  uint i;
  for (i= send_group_parts ; i-- > idx ; )
  {
    /* Get reference pointers to sum functions in place */
    memcpy((char*) ref_pointer_array,
	   (char*) rollup.ref_pointer_arrays[i],
	   ref_pointer_array_size);
    if ((!having || having->val_int()))
    {
      int error;
      Item *item;
      List_iterator_fast<Item> it(rollup.fields[i]);
      while ((item= it++))
      {
        if (item->type() == Item::NULL_ITEM && item->is_result_field())
          item->save_in_result_field(1);
      }
      copy_sum_funcs(sum_funcs_end[i+1], sum_funcs_end[i]);
      if ((error= table->file->write_row(table->record[0])))
      {
	if (create_myisam_from_heap(thd, table, &tmp_table_param,
				      error, 0))
	  return 1;		     
      }
    }
  }
  /* Restore ref_pointer_array */
  set_items_ref_array(current_ref_pointer_array);
  return 0;
}

13006 13007 13008 13009 13010 13011 13012 13013 13014 13015 13016 13017 13018 13019 13020 13021 13022 13023 13024 13025
/*
  clear results if there are not rows found for group
  (end_send_group/end_write_group)

  SYNOPSYS
     JOIN::clear()
*/

void JOIN::clear()
{
  clear_tables(this);
  copy_fields(&tmp_table_param);

  if (sum_funcs)
  {
    Item_sum *func, **func_ptr= sum_funcs;
    while ((func= *(func_ptr++)))
      func->clear();
  }
}
13026

unknown's avatar
unknown committed
13027
/****************************************************************************
13028 13029
  EXPLAIN handling

13030
  Send a description about what how the select will be done to stdout
unknown's avatar
unknown committed
13031 13032
****************************************************************************/

unknown's avatar
unknown committed
13033
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
unknown's avatar
unknown committed
13034
			    bool distinct,const char *message)
unknown's avatar
unknown committed
13035 13036
{
  List<Item> field_list;
13037
  List<Item> item_list;
unknown's avatar
unknown committed
13038
  THD *thd=join->thd;
13039
  select_result *result=join->result;
13040
  Item *item_null= new Item_null();
unknown's avatar
af  
unknown committed
13041 13042
  CHARSET_INFO *cs= system_charset_info;
  int quick_type;
unknown's avatar
unknown committed
13043
  DBUG_ENTER("select_describe");
13044
  DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
unknown's avatar
unknown committed
13045
		      (ulong)join->select_lex, join->select_lex->type,
13046
		      message ? message : "NULL"));
13047
  /* Don't log this into the slow query log */
13048
  thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
unknown's avatar
unknown committed
13049
  join->unit->offset_limit_cnt= 0;
13050

unknown's avatar
unknown committed
13051
  if (message)
unknown's avatar
unknown committed
13052
  {
unknown's avatar
af  
unknown committed
13053 13054
    item_list.push_back(new Item_int((int32)
				     join->select_lex->select_number));
unknown's avatar
unknown committed
13055
    item_list.push_back(new Item_string(join->select_lex->type,
unknown's avatar
unknown committed
13056
					strlen(join->select_lex->type), cs));
13057
    for (uint i=0 ; i < 7; i++)
13058
      item_list.push_back(item_null);
unknown's avatar
unknown committed
13059
    item_list.push_back(new Item_string(message,strlen(message),cs));
13060
    if (result->send_data(item_list))
13061
      join->error= 1;
unknown's avatar
unknown committed
13062
  }
unknown's avatar
af  
unknown committed
13063 13064 13065 13066 13067 13068 13069 13070 13071 13072 13073 13074 13075 13076 13077 13078 13079 13080 13081 13082 13083 13084 13085 13086 13087 13088 13089 13090 13091 13092 13093 13094 13095 13096 13097 13098 13099 13100 13101 13102 13103 13104 13105 13106 13107 13108 13109 13110 13111 13112 13113 13114 13115 13116 13117 13118 13119 13120 13121 13122 13123 13124 13125 13126
  else if (join->select_lex == join->unit->fake_select_lex)
  {
    /* 
      here we assume that the query will return at least two rows, so we
      show "filesort" in EXPLAIN. Of course, sometimes we'll be wrong
      and no filesort will be actually done, but executing all selects in
      the UNION to provide precise EXPLAIN information will hardly be
      appreciated :)
    */
    char table_name_buffer[NAME_LEN];
    item_list.empty();
    /* id */
    item_list.push_back(new Item_null);
    /* select_type */
    item_list.push_back(new Item_string(join->select_lex->type,
					strlen(join->select_lex->type),
					cs));
    /* table */
    {
      SELECT_LEX *sl= join->unit->first_select();
      uint len= 6, lastop= 0;
      memcpy(table_name_buffer, "<union", 6);
      for (; sl && len + lastop + 5 < NAME_LEN; sl= sl->next_select())
      {
        len+= lastop;
        lastop= my_snprintf(table_name_buffer + len, NAME_LEN - len,
                            "%u,", sl->select_number);
      }
      if (sl || len + lastop >= NAME_LEN)
      {
        memcpy(table_name_buffer + len, "...>", 5);
        len+= 4;
      }
      else
      {
        len+= lastop;
        table_name_buffer[len - 1]= '>';  // change ',' to '>'
      }
      item_list.push_back(new Item_string(table_name_buffer, len, cs));
    }
    /* type */
    item_list.push_back(new Item_string(join_type_str[JT_ALL],
					  strlen(join_type_str[JT_ALL]),
					  cs));
    /* possible_keys */
    item_list.push_back(item_null);
    /* key*/
    item_list.push_back(item_null);
    /* key_len */
    item_list.push_back(item_null);
    /* ref */
    item_list.push_back(item_null);
    /* rows */
    item_list.push_back(item_null);
    /* extra */
    if (join->unit->global_parameters->order_list.first)
      item_list.push_back(new Item_string("Using filesort",
					  14, cs));
    else
      item_list.push_back(new Item_string("", 0, cs));

    if (result->send_data(item_list))
      join->error= 1;
  }
unknown's avatar
unknown committed
13127 13128 13129 13130
  else
  {
    table_map used_tables=0;
    for (uint i=0 ; i < join->tables ; i++)
unknown's avatar
unknown committed
13131
    {
unknown's avatar
unknown committed
13132 13133
      JOIN_TAB *tab=join->join_tab+i;
      TABLE *table=tab->table;
unknown's avatar
af  
unknown committed
13134
      char buff[512]; 
unknown's avatar
unknown committed
13135 13136
      char buff1[512], buff2[512], buff3[512];
      char keylen_str_buf[64];
unknown's avatar
af  
unknown committed
13137 13138
      String extra(buff, sizeof(buff),cs);
      char table_name_buffer[NAME_LEN];
unknown's avatar
unknown committed
13139 13140
      String tmp1(buff1,sizeof(buff1),cs);
      String tmp2(buff2,sizeof(buff2),cs);
unknown's avatar
unknown committed
13141
      String tmp3(buff3,sizeof(buff3),cs);
unknown's avatar
af  
unknown committed
13142
      extra.length(0);
13143 13144
      tmp1.length(0);
      tmp2.length(0);
unknown's avatar
unknown committed
13145
      tmp3.length(0);
13146

unknown's avatar
af  
unknown committed
13147
      quick_type= -1;
unknown's avatar
unknown committed
13148
      item_list.empty();
unknown's avatar
af  
unknown committed
13149 13150
      /* id */
      item_list.push_back(new Item_uint((uint32)
unknown's avatar
unknown committed
13151
				       join->select_lex->select_number));
unknown's avatar
af  
unknown committed
13152
      /* select_type */
unknown's avatar
unknown committed
13153 13154
      item_list.push_back(new Item_string(join->select_lex->type,
					  strlen(join->select_lex->type),
unknown's avatar
unknown committed
13155
					  cs));
unknown's avatar
unknown committed
13156
      if (tab->type == JT_ALL && tab->select && tab->select->quick)
unknown's avatar
unknown committed
13157
      {
unknown's avatar
af  
unknown committed
13158 13159 13160 13161
        quick_type= tab->select->quick->get_type();
        if ((quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE) ||
            (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) ||
            (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION))
unknown's avatar
unknown committed
13162 13163 13164 13165
          tab->type = JT_INDEX_MERGE;
        else
	  tab->type = JT_RANGE;
      }
unknown's avatar
af  
unknown committed
13166
      /* table */
unknown's avatar
unknown committed
13167
      if (table->derived_select_number)
unknown's avatar
unknown committed
13168
      {
unknown's avatar
unknown committed
13169
	/* Derived table name generation */
unknown's avatar
af  
unknown committed
13170
	int len= my_snprintf(table_name_buffer, sizeof(table_name_buffer)-1,
unknown's avatar
unknown committed
13171
			     "<derived%u>",
unknown's avatar
unknown committed
13172
			     table->derived_select_number);
unknown's avatar
af  
unknown committed
13173
	item_list.push_back(new Item_string(table_name_buffer, len, cs));
unknown's avatar
unknown committed
13174 13175
      }
      else
13176 13177
	item_list.push_back(new Item_string(table->alias,
					    strlen(table->alias),
unknown's avatar
unknown committed
13178
					    cs));
unknown's avatar
af  
unknown committed
13179
      /* type */
13180 13181
      item_list.push_back(new Item_string(join_type_str[tab->type],
					  strlen(join_type_str[tab->type]),
unknown's avatar
unknown committed
13182
					  cs));
unknown's avatar
af  
unknown committed
13183
      /* Build "possible_keys" value and add it to item_list */
13184
      if (!tab->keys.is_clear_all())
unknown's avatar
unknown committed
13185
      {
unknown's avatar
unknown committed
13186
        uint j;
13187
        for (j=0 ; j < table->s->keys ; j++)
13188 13189 13190 13191 13192
        {
          if (tab->keys.is_set(j))
          {
            if (tmp1.length())
              tmp1.append(',');
unknown's avatar
af  
unknown committed
13193 13194 13195
            tmp1.append(table->key_info[j].name, 
			strlen(table->key_info[j].name),
			system_charset_info);
13196 13197
          }
        }
unknown's avatar
unknown committed
13198
      }
13199
      if (tmp1.length())
unknown's avatar
unknown committed
13200
	item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),cs));
unknown's avatar
unknown committed
13201
      else
13202
	item_list.push_back(item_null);
unknown's avatar
af  
unknown committed
13203 13204

      /* Build "key", "key_len", and "ref" values and add them to item_list */
unknown's avatar
unknown committed
13205
      if (tab->ref.key_parts)
unknown's avatar
unknown committed
13206
      {
13207
	KEY *key_info=table->key_info+ tab->ref.key;
unknown's avatar
unknown committed
13208
        register uint length;
13209
	item_list.push_back(new Item_string(key_info->name,
13210 13211
					    strlen(key_info->name),
					    system_charset_info));
unknown's avatar
unknown committed
13212 13213 13214 13215
        length= longlong2str(tab->ref.key_length, keylen_str_buf, 10) - 
                keylen_str_buf;
        item_list.push_back(new Item_string(keylen_str_buf, length,
                                            system_charset_info));
unknown's avatar
unknown committed
13216 13217
	for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
	{
13218 13219
	  if (tmp2.length())
	    tmp2.append(',');
unknown's avatar
af  
unknown committed
13220 13221
	  tmp2.append((*ref)->name(), strlen((*ref)->name()),
		      system_charset_info);
unknown's avatar
unknown committed
13222
	}
unknown's avatar
unknown committed
13223
	item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
unknown's avatar
unknown committed
13224 13225 13226
      }
      else if (tab->type == JT_NEXT)
      {
13227
	KEY *key_info=table->key_info+ tab->index;
unknown's avatar
unknown committed
13228
        register uint length;
13229
	item_list.push_back(new Item_string(key_info->name,
unknown's avatar
unknown committed
13230
					    strlen(key_info->name),cs));
unknown's avatar
unknown committed
13231 13232 13233 13234 13235
        length= longlong2str(key_info->key_length, keylen_str_buf, 10) - 
                keylen_str_buf;
        item_list.push_back(new Item_string(keylen_str_buf, 
                                            length,
                                            system_charset_info));
13236
	item_list.push_back(item_null);
unknown's avatar
unknown committed
13237 13238 13239
      }
      else if (tab->select && tab->select->quick)
      {
unknown's avatar
af  
unknown committed
13240
        tab->select->quick->add_keys_and_lengths(&tmp2, &tmp3);
unknown's avatar
unknown committed
13241
	item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
unknown's avatar
af  
unknown committed
13242
	item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs));
13243
	item_list.push_back(item_null);
unknown's avatar
unknown committed
13244 13245 13246
      }
      else
      {
13247 13248 13249
	item_list.push_back(item_null);
	item_list.push_back(item_null);
	item_list.push_back(item_null);
unknown's avatar
unknown committed
13250
      }
unknown's avatar
af  
unknown committed
13251
      /* Add "rows" field to item_list. */
13252 13253 13254
      item_list.push_back(new Item_int((longlong) (ulonglong)
				       join->best_positions[i]. records_read,
				       21));
unknown's avatar
af  
unknown committed
13255
      /* Build "Extra" field and add it to item_list. */
unknown's avatar
unknown committed
13256
      my_bool key_read=table->key_read;
unknown's avatar
af  
unknown committed
13257 13258
      if ((tab->type == JT_NEXT || tab->type == JT_CONST) &&
          table->used_keys.is_set(tab->index))
unknown's avatar
unknown committed
13259
	key_read=1;
unknown's avatar
af  
unknown committed
13260 13261 13262 13263
      if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT &&
          !((QUICK_ROR_INTERSECT_SELECT*)tab->select->quick)->need_to_fetch_row)
        key_read=1;
        
unknown's avatar
unknown committed
13264
      if (tab->info)
unknown's avatar
unknown committed
13265
	item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs));
13266
      else
unknown's avatar
unknown committed
13267
      {
unknown's avatar
af  
unknown committed
13268 13269 13270 13271 13272 13273 13274
        if (quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION || 
            quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
            quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE)
        {
          extra.append("; Using ");
          tab->select->quick->add_info_string(&extra);
        }
13275
	if (tab->select)
unknown's avatar
unknown committed
13276
	{
13277 13278
	  if (tab->use_quick == 2)
	  {
13279
            char buf[MAX_KEY/8+1];
unknown's avatar
af  
unknown committed
13280 13281 13282
            extra.append("; Range checked for each record (index map: 0x");
            extra.append(tab->keys.print(buf));
            extra.append(')');
13283
	  }
13284
	  else if (tab->select->cond)
13285 13286 13287 13288 13289 13290 13291 13292 13293 13294 13295 13296 13297 13298 13299
          {
            const COND *pushed_cond= tab->table->file->pushed_cond;

            if (thd->variables.engine_condition_pushdown && pushed_cond)
            {
              extra.append("; Using where with pushed condition");
              if (thd->lex->describe & DESCRIBE_EXTENDED)
              {
                extra.append(": ");
                ((COND *)pushed_cond)->print(&extra);
              }
            }
            else
              extra.append("; Using where");
          }
unknown's avatar
unknown committed
13300
	}
13301
	if (key_read)
13302 13303 13304 13305 13306 13307
        {
          if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
            extra.append("; Using index for group-by");
          else
            extra.append("; Using index");
        }
13308
	if (table->reginfo.not_exists_optimize)
unknown's avatar
af  
unknown committed
13309
	  extra.append("; Not exists");
13310 13311 13312
	if (need_tmp_table)
	{
	  need_tmp_table=0;
unknown's avatar
af  
unknown committed
13313
	  extra.append("; Using temporary");
13314 13315 13316 13317
	}
	if (need_order)
	{
	  need_order=0;
unknown's avatar
af  
unknown committed
13318
	  extra.append("; Using filesort");
13319
	}
13320
	if (distinct & test_all_bits(used_tables,thd->used_tables))
unknown's avatar
af  
unknown committed
13321 13322 13323 13324 13325 13326 13327 13328 13329 13330 13331
	  extra.append("; Distinct");
        
        /* Skip initial "; "*/
        const char *str= extra.ptr();
        uint32 len= extra.length();
        if (len)
        {
          str += 2;
          len -= 2;
        }
	item_list.push_back(new Item_string(str, len, cs));
unknown's avatar
unknown committed
13332 13333 13334
      }
      // For next iteration
      used_tables|=table->map;
13335
      if (result->send_data(item_list))
13336
	join->error= 1;
unknown's avatar
unknown committed
13337
    }
unknown's avatar
unknown committed
13338
  }
unknown's avatar
unknown committed
13339 13340 13341 13342 13343 13344 13345
  for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit();
       unit;
       unit= unit->next_unit())
  {
    if (mysql_explain_union(thd, unit, result))
      DBUG_VOID_RETURN;
  }
unknown's avatar
unknown committed
13346 13347 13348
  DBUG_VOID_RETURN;
}

13349

unknown's avatar
unknown committed
13350
bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
unknown's avatar
unknown committed
13351
{
unknown's avatar
unknown committed
13352
  DBUG_ENTER("mysql_explain_union");
unknown's avatar
unknown committed
13353
  bool res= 0;
unknown's avatar
unknown committed
13354
  SELECT_LEX *first= unit->first_select();
unknown's avatar
af  
unknown committed
13355

unknown's avatar
unknown committed
13356 13357 13358 13359
  for (SELECT_LEX *sl= first;
       sl;
       sl= sl->next_select())
  {
unknown's avatar
af  
unknown committed
13360 13361 13362 13363 13364 13365 13366 13367 13368 13369 13370 13371 13372 13373 13374 13375 13376 13377 13378 13379 13380 13381 13382
    // drop UNCACHEABLE_EXPLAIN, because it is for internal usage only
    uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN);
    sl->type= (((&thd->lex->select_lex)==sl)?
	       ((thd->lex->all_selects_list != sl) ? 
		primary_key_name : "SIMPLE"):
	       ((sl == first)?
		((sl->linkage == DERIVED_TABLE_TYPE) ?
		 "DERIVED":
		 ((uncacheable & UNCACHEABLE_DEPENDENT) ?
		  "DEPENDENT SUBQUERY":
		  (uncacheable?"UNCACHEABLE SUBQUERY":
		   "SUBQUERY"))):
		((uncacheable & UNCACHEABLE_DEPENDENT) ?
		 "DEPENDENT UNION":
		 uncacheable?"UNCACHEABLE UNION":
		 "UNION")));
    sl->options|= SELECT_DESCRIBE;
  }
  if (first->next_select())
  {
    unit->fake_select_lex->select_number= UINT_MAX; // jost for initialization
    unit->fake_select_lex->type= "UNION RESULT";
    unit->fake_select_lex->options|= SELECT_DESCRIBE;
13383 13384
    if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE,
                             "")))
unknown's avatar
af  
unknown committed
13385 13386 13387 13388 13389 13390 13391 13392 13393 13394 13395 13396 13397 13398 13399 13400 13401 13402 13403
      res= unit->exec();
    res|= unit->cleanup();
  }
  else
  {
    thd->lex->current_select= first;
    unit->set_limit(unit->global_parameters, first);
    res= mysql_select(thd, &first->ref_pointer_array,
			(TABLE_LIST*) first->table_list.first,
			first->with_wild, first->item_list,
			first->where,
			first->order_list.elements +
			first->group_list.elements,
			(ORDER*) first->order_list.first,
			(ORDER*) first->group_list.first,
			first->having,
			(ORDER*) thd->lex->proc_list.first,
			first->options | thd->options | SELECT_DESCRIBE,
			result, unit, first);
unknown's avatar
unknown committed
13404
  }
unknown's avatar
unknown committed
13405
  DBUG_RETURN(res || thd->net.report_error);
unknown's avatar
unknown committed
13406 13407
}

13408

13409 13410 13411 13412 13413 13414
/*
  Print joins from the FROM clause

  SYNOPSIS
    print_join()
    thd     thread handler
13415
    str     string where table should be printed
13416 13417 13418 13419 13420 13421 13422 13423 13424 13425 13426 13427 13428 13429 13430 13431
    tables  list of tables in join
*/

static void print_join(THD *thd, String *str, List<TABLE_LIST> *tables)
{
  /* List is reversed => we should reverse it before using */
  List_iterator_fast<TABLE_LIST> ti(*tables);
  TABLE_LIST **table= (TABLE_LIST **)thd->alloc(sizeof(TABLE_LIST*) *
                                                tables->elements);
  if (table == 0)
    return;  // out of memory

  for (TABLE_LIST **t= table + (tables->elements - 1); t >= table; t--)
    *t= ti++;

  DBUG_ASSERT(tables->elements >= 1);
unknown's avatar
unknown committed
13432
  (*table)->print(thd, str);
13433 13434 13435 13436 13437

  TABLE_LIST **end= table + tables->elements;
  for(TABLE_LIST **tbl= table + 1; tbl < end; tbl++)
  {
    TABLE_LIST *curr= *tbl;
unknown's avatar
unknown committed
13438
    if (curr->outer_join)
unknown's avatar
unknown committed
13439
      str->append(" left join ", 11); // MySQL converts right to left joins
13440 13441 13442 13443 13444 13445 13446 13447 13448 13449 13450 13451 13452 13453 13454 13455 13456 13457 13458 13459 13460 13461 13462 13463 13464 13465 13466 13467 13468 13469 13470
    else if (curr->straight)
      str->append(" straight_join ", 15);
    else
      str->append(" join ", 6);
    curr->print(thd, str);
    if (curr->on_expr)
    {
      str->append(" on(", 4);
      curr->on_expr->print(str);
      str->append(')');
    }
  }
}


/*
  Print table as it should be in join list

  SYNOPSIS
    st_table_list::print();
    str   string where table should bbe printed
*/

void st_table_list::print(THD *thd, String *str)
{
  if (nested_join)
  {
    str->append('(');
    print_join(thd, str, &nested_join->join_list);
    str->append(')');
  }
13471
  else
unknown's avatar
VIEW  
unknown committed
13472
  {
13473 13474
    const char *cmp_name;                         // Name to compare with alias
    if (view_name.str)
unknown's avatar
VIEW  
unknown committed
13475
    {
13476 13477 13478 13479
      append_identifier(thd, str, view_db.str, view_db.length);
      str->append('.');
      append_identifier(thd, str, view_name.str, view_name.length);
      cmp_name= view_name.str;
unknown's avatar
VIEW  
unknown committed
13480
    }
13481 13482 13483 13484 13485 13486 13487 13488 13489 13490 13491
    else if (derived)
    {
      str->append('(');
      derived->print(str);
      str->append(')');
      cmp_name= "";                               // Force printing of alias
    }
    else
    {
      append_identifier(thd, str, db, db_length);
      str->append('.');
13492 13493
      if (schema_table)
      {
unknown's avatar
unknown committed
13494 13495 13496
        append_identifier(thd, str, schema_table_name,
                          strlen(schema_table_name));
        cmp_name= schema_table_name;
13497 13498 13499
      }
      else
      {
13500 13501
        append_identifier(thd, str, table_name, table_name_length);
        cmp_name= table_name;
13502
      }
13503 13504
    }
    if (my_strcasecmp(table_alias_charset, cmp_name, alias))
13505 13506
    {
      str->append(' ');
13507
      append_identifier(thd, str, alias, strlen(alias));
13508 13509 13510 13511
    }
  }
}

13512

unknown's avatar
unknown committed
13513 13514
void st_select_lex::print(THD *thd, String *str)
{
unknown's avatar
unknown committed
13515
  /* QQ: thd may not be set for sub queries, but this should be fixed */
unknown's avatar
unknown committed
13516 13517 13518
  if (!thd)
    thd= current_thd;

13519
  str->append("select ", 7);
13520

13521
  /* First add options */
unknown's avatar
unknown committed
13522
  if (options & SELECT_STRAIGHT_JOIN)
13523
    str->append("straight_join ", 14);
unknown's avatar
af  
unknown committed
13524
  if ((thd->lex->lock_option == TL_READ_HIGH_PRIORITY) &&
unknown's avatar
unknown committed
13525
      (this == &thd->lex->select_lex))
13526
    str->append("high_priority ", 14);
unknown's avatar
unknown committed
13527
  if (options & SELECT_DISTINCT)
13528
    str->append("distinct ", 9);
unknown's avatar
unknown committed
13529
  if (options & SELECT_SMALL_RESULT)
unknown's avatar
af  
unknown committed
13530
    str->append("sql_small_result ", 17);
unknown's avatar
unknown committed
13531
  if (options & SELECT_BIG_RESULT)
unknown's avatar
af  
unknown committed
13532
    str->append("sql_big_result ", 15);
unknown's avatar
unknown committed
13533
  if (options & OPTION_BUFFER_RESULT)
unknown's avatar
af  
unknown committed
13534
    str->append("sql_buffer_result ", 18);
unknown's avatar
unknown committed
13535
  if (options & OPTION_FOUND_ROWS)
unknown's avatar
af  
unknown committed
13536
    str->append("sql_calc_found_rows ", 20);
unknown's avatar
unknown committed
13537
  if (!thd->lex->safe_to_cache_query)
unknown's avatar
af  
unknown committed
13538
    str->append("sql_no_cache ", 13);
unknown's avatar
unknown committed
13539
  if (options & OPTION_TO_QUERY_CACHE)
unknown's avatar
af  
unknown committed
13540
    str->append("sql_cache ", 10);
unknown's avatar
unknown committed
13541 13542 13543 13544 13545 13546 13547 13548 13549 13550 13551 13552 13553 13554 13555 13556 13557 13558 13559 13560

  //Item List
  bool first= 1;
  List_iterator_fast<Item> it(item_list);
  Item *item;
  while ((item= it++))
  {
    if (first)
      first= 0;
    else
      str->append(',');
    item->print_item_w_name(str);
  }

  /*
    from clause
    TODO: support USING/FORCE/IGNORE index
  */
  if (table_list.elements)
  {
13561
    str->append(" from ", 6);
13562 13563
    /* go through join tree */
    print_join(thd, str, &top_join_list);
unknown's avatar
unknown committed
13564 13565
  }

13566 13567
  // Where
  Item *cur_where= where;
unknown's avatar
unknown committed
13568
  if (join)
13569 13570
    cur_where= join->conds;
  if (cur_where)
unknown's avatar
unknown committed
13571
  {
13572
    str->append(" where ", 7);
13573
    cur_where->print(str);
unknown's avatar
unknown committed
13574 13575
  }

13576
  // group by & olap
unknown's avatar
unknown committed
13577 13578
  if (group_list.elements)
  {
13579
    str->append(" group by ", 10);
unknown's avatar
unknown committed
13580 13581 13582 13583
    print_order(str, (ORDER *) group_list.first);
    switch (olap)
    {
      case CUBE_TYPE:
13584
	str->append(" with cube", 10);
unknown's avatar
unknown committed
13585 13586
	break;
      case ROLLUP_TYPE:
13587
	str->append(" with rollup", 12);
unknown's avatar
unknown committed
13588 13589 13590 13591 13592 13593
	break;
      default:
	;  //satisfy compiler
    }
  }

13594 13595
  // having
  Item *cur_having= having;
unknown's avatar
unknown committed
13596
  if (join)
13597
    cur_having= join->having;
unknown's avatar
unknown committed
13598

13599
  if (cur_having)
unknown's avatar
unknown committed
13600
  {
13601
    str->append(" having ", 8);
13602
    cur_having->print(str);
unknown's avatar
unknown committed
13603 13604 13605 13606
  }

  if (order_list.elements)
  {
13607
    str->append(" order by ", 10);
unknown's avatar
unknown committed
13608 13609 13610 13611 13612 13613 13614 13615
    print_order(str, (ORDER *) order_list.first);
  }

  // limit
  print_limit(thd, str);

  // PROCEDURE unsupported here
}
unknown's avatar
af  
unknown committed
13616 13617 13618 13619 13620 13621 13622 13623 13624 13625


/*
  change select_result object of JOIN

  SYNOPSIS
    JOIN::change_result()
    res		new select_result object

  RETURN
unknown's avatar
unknown committed
13626 13627
    FALSE - OK
    TRUE  - error
unknown's avatar
af  
unknown committed
13628 13629
*/

unknown's avatar
unknown committed
13630
bool JOIN::change_result(select_result *res)
unknown's avatar
af  
unknown committed
13631 13632 13633
{
  DBUG_ENTER("JOIN::change_result");
  result= res;
13634 13635
  if (!procedure && (result->prepare(fields_list, select_lex->master_unit()) ||
                     result->prepare2()))
unknown's avatar
af  
unknown committed
13636
  {
unknown's avatar
unknown committed
13637
    DBUG_RETURN(TRUE);
unknown's avatar
af  
unknown committed
13638
  }
unknown's avatar
unknown committed
13639
  DBUG_RETURN(FALSE);
unknown's avatar
af  
unknown committed
13640
}