sql_select.cc 387 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 67 68 69 70
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);
/*
  TODO: 'find_best' is here only temporarily until 'greedy_search' is
  tested and approved.
*/
unknown's avatar
unknown committed
71 72 73 74 75
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
76 77
static store_key *get_store_key(THD *thd,
				KEYUSE *keyuse, table_map used_tables,
unknown's avatar
unknown committed
78 79 80
				KEY_PART_INFO *key_part, char *key_buff,
				uint maybe_null);
static bool make_simple_join(JOIN *join,TABLE *tmp_table);
81
static void make_outerjoin_info(JOIN *join);
unknown's avatar
unknown committed
82 83
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
static void make_join_readinfo(JOIN *join,uint options);
84
static bool only_eq_ref_tables(JOIN *join, ORDER *order, table_map tables);
unknown's avatar
unknown committed
85 86 87 88
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);
89
static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
unknown's avatar
unknown committed
90 91
			    List<Item> &fields, bool send_row,
			    uint select_options, const char *info,
92 93
			    Item *having, Procedure *proc,
			    SELECT_LEX_UNIT *unit);
unknown's avatar
unknown committed
94
static COND *build_equal_items(THD *thd, COND *cond,
unknown's avatar
unknown committed
95 96 97
                               COND_EQUAL *inherited,
                               List<TABLE_LIST> *join_list,
                               COND_EQUAL **cond_equal_ref);
98
static COND* substitute_for_best_equal_field(COND *cond,
unknown's avatar
unknown committed
99
                                             COND_EQUAL *cond_equal,
100
                                             void *table_join_idx);
101 102
static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list,
                            COND *conds, bool top);
unknown's avatar
unknown committed
103
static COND *optimize_cond(JOIN *join, COND *conds,
unknown's avatar
unknown committed
104
                           List<TABLE_LIST> *join_list,
unknown's avatar
af  
unknown committed
105
			   Item::cond_result *cond_value);
106
static bool resolve_nested_join (TABLE_LIST *table);
unknown's avatar
af  
unknown committed
107 108
static COND *remove_eq_conds(THD *thd, COND *cond, 
			     Item::cond_result *cond_value);
unknown's avatar
unknown committed
109 110 111
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,
112
				    ulong options);
unknown's avatar
unknown committed
113 114 115 116
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
117
static int flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last);
unknown's avatar
unknown committed
118 119 120 121 122 123 124 125 126
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);
127
static int join_read_const_table(JOIN_TAB *tab, POSITION *pos);
unknown's avatar
unknown committed
128 129 130 131
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);
132
static int join_read_last_key(JOIN_TAB *tab);
unknown's avatar
unknown committed
133 134 135 136 137
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);
138 139 140 141 142 143
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
144 145
static int join_ft_read_first(JOIN_TAB *tab);
static int join_ft_read_next(READ_RECORD *info);
146 147
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
148 149 150
static COND *make_cond_for_table(COND *cond,table_map table,
				 table_map used_table);
static Item* part_of_refkey(TABLE *form,Field *field);
151
uint find_shortest_key(TABLE *table, const key_map *usable_keys);
unknown's avatar
unknown committed
152
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
153
				    ha_rows select_limit, bool no_changes);
154
static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
unknown's avatar
unknown committed
155
			     ha_rows filesort_limit, ha_rows select_limit);
156 157
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
			     Item *having);
unknown's avatar
unknown committed
158
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
159
				   ulong offset,Item *having);
unknown's avatar
unknown committed
160
static int remove_dup_with_hash_index(THD *thd,TABLE *table,
unknown's avatar
unknown committed
161
				      uint field_count, Field **first_field,
162

163
				      ulong key_length,Item *having);
unknown's avatar
unknown committed
164 165 166
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);
167 168
static void reset_cache_read(JOIN_CACHE *cache);
static void reset_cache_write(JOIN_CACHE *cache);
unknown's avatar
unknown committed
169 170 171 172
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);
173 174 175
static ORDER *create_distinct_group(THD *thd, ORDER *order,
				    List<Item> &fields,
				    bool *all_order_by_fields_used);
unknown's avatar
unknown committed
176 177 178
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);
179
static bool make_group_fields(JOIN *main_join, JOIN *curr_join);
unknown's avatar
unknown committed
180
static bool alloc_group_fields(JOIN *join,ORDER *group);
181
// Create list for using with tempory table
182
static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
183 184 185 186 187 188 189 190
				     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
191 192 193 194
static void init_tmptable_sum_functions(Item_sum **func);
static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
static void copy_sum_funcs(Item_sum **func_ptr);
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
195
static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr);
196
static bool init_sum_functions(Item_sum **func, Item_sum **end);
unknown's avatar
unknown committed
197
static bool update_sum_func(Item_sum **func);
198
static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
unknown's avatar
unknown committed
199
			    bool distinct, const char *message=NullS);
200
static Item *remove_additional_cond(Item* conds);
201
static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab);
unknown's avatar
unknown committed
202

203

204 205 206 207
/*
  This handles SELECT with and without UNION
*/

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

unknown's avatar
unknown committed
214
  if (select_lex->next_select())
unknown's avatar
af  
unknown committed
215
    res= mysql_union(thd, lex, result, &lex->unit);
216
  else
unknown's avatar
af  
unknown committed
217 218 219
  {
    SELECT_LEX_UNIT *unit= &lex->unit;
    unit->set_limit(unit->global_parameters, select_lex);
220 221 222 223 224 225 226 227 228 229 230
    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,
		      select_lex->options | thd->options,
unknown's avatar
af  
unknown committed
231 232
		      result, unit, select_lex);
  }
233 234
  DBUG_PRINT("info",("res: %d  report_error: %d", res,
		     thd->net.report_error));
unknown's avatar
unknown committed
235
  res|= thd->net.report_error;
236
  if (unlikely(res))
237
  {
unknown's avatar
unknown committed
238 239 240
    /*
      If we have real error reported erly then this will be ignored
    */
unknown's avatar
unknown committed
241
    result->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR));
242
    result->abort();
unknown's avatar
unknown committed
243
  }
244
  DBUG_RETURN(res);
245 246
}

247

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

  save_allow_sum_func= thd->allow_sum_func;
265
  thd->allow_sum_func= 0;
unknown's avatar
unknown committed
266
  res= setup_conds(thd, tables, leaves, conds);
unknown's avatar
unknown committed
267 268 269 270 271 272
  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);
273
  thd->allow_sum_func= save_allow_sum_func;
unknown's avatar
af  
unknown committed
274
  DBUG_RETURN(res);
275 276
}

unknown's avatar
unknown committed
277
/*****************************************************************************
278 279
  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
280 281
*****************************************************************************/

282
/*
unknown's avatar
af  
unknown committed
283
  Prepare of whole select (including sub queries in future).
284 285 286
  return -1 on error
          0 on success
*/
unknown's avatar
unknown committed
287
int
288 289 290 291
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
292
	      Item *having_init,
293 294
	      ORDER *proc_param_init, SELECT_LEX *select_lex_arg,
	      SELECT_LEX_UNIT *unit_arg)
unknown's avatar
unknown committed
295
{
296
  DBUG_ENTER("JOIN::prepare");
unknown's avatar
unknown committed
297

unknown's avatar
af  
unknown committed
298 299 300 301
  // to prevent double initialization on EXPLAIN
  if (optimized)
    DBUG_RETURN(0);

302 303 304 305 306 307
  conds= conds_init;
  order= order_init;
  group_list= group_init;
  having= having_init;
  proc_param= proc_param_init;
  tables_list= tables_init;
308
  select_lex= select_lex_arg;
309
  select_lex->join= this;
310
  join_list= &select_lex->top_join_list;
311
  union_part= (unit_arg->first_select()->next_select() != 0);
unknown's avatar
unknown committed
312 313 314

  /* Check that all tables, fields, conds and order are ok */

unknown's avatar
unknown committed
315 316
  if (setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables,
                   FALSE, FALSE) ||
317
      setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
unknown's avatar
unknown committed
318
      select_lex->setup_ref_array(thd, og_num) ||
319 320
      setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
		   &all_fields, 1) ||
321 322 323
      setup_without_group(thd, (*rref_pointer_array), tables_list,
			  select_lex->leaf_tables, fields_list,
			  all_fields, &conds, order, group_list,
324
			  &hidden_group_fields))
unknown's avatar
unknown committed
325 326
    DBUG_RETURN(-1);				/* purecov: inspected */

327
  ref_pointer_array= *rref_pointer_array;
328
  
unknown's avatar
unknown committed
329 330 331 332
  if (having)
  {
    thd->where="having clause";
    thd->allow_sum_func=1;
unknown's avatar
unknown committed
333
    select_lex->having_fix_field= 1;
unknown's avatar
af  
unknown committed
334 335 336
    bool having_fix_rc= (!having->fixed &&
			 (having->fix_fields(thd, tables_list, &having) ||
			  having->check_cols(1)));
unknown's avatar
unknown committed
337
    select_lex->having_fix_field= 0;
unknown's avatar
unknown committed
338
    if (having_fix_rc || thd->net.report_error)
unknown's avatar
unknown committed
339 340
      DBUG_RETURN(-1);				/* purecov: inspected */
    if (having->with_sum_func)
341
      having->split_sum_func(thd, ref_pointer_array, all_fields);
unknown's avatar
unknown committed
342
  }
343

unknown's avatar
VIEW  
unknown committed
344
  if (!thd->lex->view_prepare_mode)
345 346
  {
    Item_subselect *subselect;
unknown's avatar
VIEW  
unknown committed
347
    /* Is it subselect? */
unknown's avatar
af  
unknown committed
348
    if ((subselect= select_lex->master_unit()->item))
349 350
    {
      Item_subselect::trans_res res;
351
      if ((res= subselect->select_transformer(this)) !=
352
	  Item_subselect::RES_OK)
unknown's avatar
af  
unknown committed
353
      {
unknown's avatar
VIEW  
unknown committed
354
        select_lex->fix_prepare_information(thd, &conds);
355
	DBUG_RETURN((res == Item_subselect::RES_ERROR));
unknown's avatar
af  
unknown committed
356
      }
357 358 359
    }
  }

360
  if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
unknown's avatar
unknown committed
361
    DBUG_RETURN(-1);
362 363
  

unknown's avatar
unknown committed
364 365 366 367 368
  /*
    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;
369
  */
unknown's avatar
unknown committed
370
  {
371
    if (!group_list)
unknown's avatar
unknown committed
372 373
    {
      uint flag=0;
374
      List_iterator_fast<Item> it(fields_list);
unknown's avatar
unknown committed
375 376 377 378 379
      Item *item;
      while ((item= it++))
      {
	if (item->with_sum_func)
	  flag|=1;
unknown's avatar
af  
unknown committed
380
	else if (!(flag & 2) && !item->const_during_execution())
unknown's avatar
unknown committed
381 382 383 384
	  flag|=2;
      }
      if (flag == 3)
      {
unknown's avatar
unknown committed
385 386
	my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
                   ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));
unknown's avatar
unknown committed
387 388 389
	DBUG_RETURN(-1);
      }
    }
390
    TABLE_LIST *table_ptr;
391 392 393
    for (table_ptr= select_lex->leaf_tables;
	 table_ptr;
	 table_ptr= table_ptr->next_leaf)
394
      tables++;
unknown's avatar
unknown committed
395
  }
396 397 398
  {
    /* Caclulate the number of groups */
    send_group_parts= 0;
399
    for (ORDER *group_tmp= group_list ; group_tmp ; group_tmp= group_tmp->next)
400 401 402
      send_group_parts++;
  }
  
403
  procedure= setup_procedure(thd, proc_param, result, fields_list, &error);
unknown's avatar
unknown committed
404
  if (error)
405
    goto err;					/* purecov: inspected */
unknown's avatar
unknown committed
406 407
  if (procedure)
  {
408 409
    if (setup_new_fields(thd, tables_list, fields_list, all_fields,
			 procedure->param_fields))
410
	goto err;				/* purecov: inspected */
unknown's avatar
unknown committed
411 412
    if (procedure->group)
    {
413
      if (!test_if_subpart(procedure->group,group_list))
unknown's avatar
unknown committed
414
      {						/* purecov: inspected */
unknown's avatar
unknown committed
415 416
	my_message(ER_DIFF_GROUPS_PROC, ER(ER_DIFF_GROUPS_PROC),
                   MYF(0));                     /* purecov: inspected */
417
	goto err;				/* purecov: inspected */
unknown's avatar
unknown committed
418 419 420
      }
    }
#ifdef NOT_NEEDED
421
    else if (!group_list && procedure->flags & PROC_GROUP)
unknown's avatar
unknown committed
422
    {
unknown's avatar
unknown committed
423
      my_message(ER_NO_GROUP_FOR_PROC, MYF(0));
424
      goto err;
unknown's avatar
unknown committed
425 426 427
    }
#endif
    if (order && (procedure->flags & PROC_NO_SORT))
428
    {						/* purecov: inspected */
unknown's avatar
unknown committed
429 430
      my_message(ER_ORDER_WITH_PROC, ER(ER_ORDER_WITH_PROC),
                 MYF(0));                       /* purecov: inspected */
431
      goto err;					/* purecov: inspected */
unknown's avatar
unknown committed
432 433 434 435
    }
  }

  /* Init join struct */
436
  count_field_types(&tmp_table_param, all_fields, 0);
437
  ref_pointer_array_size= all_fields.elements*sizeof(Item*);
438 439
  this->group= group_list != 0;
  row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
440
	      unit_arg->select_limit_cnt);
unknown's avatar
unknown committed
441
  /* select_limit is used to decide if we are likely to scan the whole table */
442
  select_limit= unit_arg->select_limit_cnt;
unknown's avatar
unknown committed
443 444
  if (having || (select_options & OPTION_FOUND_ROWS))
    select_limit= HA_POS_ERROR;
445 446
  do_send_rows = (unit_arg->select_limit_cnt) ? 1 : 0;
  unit= unit_arg;
unknown's avatar
unknown committed
447 448

#ifdef RESTRICTED_GROUP
449
  if (sum_func_count && !group_list && (func_count || field_count))
unknown's avatar
unknown committed
450
  {
unknown's avatar
unknown committed
451
    my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0));
452
    goto err;
unknown's avatar
unknown committed
453 454
  }
#endif
unknown's avatar
af  
unknown committed
455
  if (!procedure && result && result->prepare(fields_list, unit_arg))
456 457 458 459 460 461 462
    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
463
  select_lex->fix_prepare_information(thd, &conds);
464
  DBUG_RETURN(0); // All OK
465 466 467 468 469

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

472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
/*
  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 &&
488
      ((Item_func *)this->conds)->functype() == Item_func::EQ_FUNC &&
489 490 491 492 493 494 495 496 497 498 499
      ((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)
  {
500 501 502 503
    if ((*where= remove_additional_cond(conds)))
      join_tab->info= "Using index; Using where";
    else
      join_tab->info= "Using index";
504 505 506 507 508
    return 1;
  }
  return 0;
}

509 510 511
/*
  global select optimisation.
  return 0 - success
512
         1 - error
513 514 515 516 517 518
  error code saved in field 'error'
*/
int
JOIN::optimize()
{
  DBUG_ENTER("JOIN::optimize");
unknown's avatar
unknown committed
519
  // to prevent double initialization on EXPLAIN
520 521 522
  if (optimized)
    DBUG_RETURN(0);
  optimized= 1;
unknown's avatar
unknown committed
523

524
  // Ignore errors of execution if option IGNORE present
525 526
  if (thd->lex->duplicates == DUP_IGNORE)
    thd->lex->current_select->no_error= 1;
unknown's avatar
unknown committed
527 528
#ifdef HAVE_REF_TO_FIELDS			// Not done yet
  /* Add HAVING to WHERE if possible */
529
  if (having && !group_list && !sum_func_count)
unknown's avatar
unknown committed
530 531 532
  {
    if (!conds)
    {
533 534
      conds= having;
      having= 0;
unknown's avatar
unknown committed
535 536 537
    }
    else if ((conds=new Item_cond_and(conds,having)))
    {
unknown's avatar
unknown committed
538
      conds->fix_fields(thd, tables_list, &conds);
539
      conds->change_ref_to_fields(thd, tables_list);
540
      conds->top_level_item();
541
      having= 0;
unknown's avatar
unknown committed
542 543 544
    }
  }
#endif
unknown's avatar
unknown committed
545 546
  SELECT_LEX *sel= thd->lex->current_select;
  if (sel->first_cond_optimization)
547
  {
unknown's avatar
unknown committed
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
    /*
      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);
568 569
  }

unknown's avatar
unknown committed
570
  conds= optimize_cond(this, conds, join_list, &cond_value);   
571
  if (thd->net.report_error)
unknown's avatar
unknown committed
572
  {
unknown's avatar
unknown committed
573
    error= 1;
574
    DBUG_PRINT("error",("Error from optimize_cond"));
575
    DBUG_RETURN(1);
unknown's avatar
unknown committed
576
  }
unknown's avatar
unknown committed
577

unknown's avatar
unknown committed
578 579
  if (cond_value == Item::COND_FALSE ||
      (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
unknown's avatar
unknown committed
580
  {						/* Impossible cond */
581
    DBUG_PRINT("info", ("Impossible WHERE"));
582
    zero_result_cause= "Impossible WHERE";
583
    error= 0;
584
    DBUG_RETURN(0);
unknown's avatar
unknown committed
585 586 587
  }

  /* Optimize count(*), min() and max() */
588
  if (tables_list && tmp_table_param.sum_func_count && ! group_list)
unknown's avatar
unknown committed
589 590
  {
    int res;
unknown's avatar
unknown committed
591
    /*
unknown's avatar
unknown committed
592 593
      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
594
    */
595
    if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds)))
unknown's avatar
unknown committed
596
    {
unknown's avatar
unknown committed
597 598
      if (res > 1)
      {
599
        DBUG_PRINT("error",("Error from opt_sum_query"));
600
	DBUG_RETURN(1);
unknown's avatar
unknown committed
601
      }
unknown's avatar
unknown committed
602 603
      if (res < 0)
      {
604
        DBUG_PRINT("info",("No matching min/max row"));
605
	zero_result_cause= "No matching min/max row";
unknown's avatar
unknown committed
606
	error=0;
607
	DBUG_RETURN(0);
unknown's avatar
unknown committed
608
      }
609
      DBUG_PRINT("info",("Select tables optimized away"));
unknown's avatar
unknown committed
610
      zero_result_cause= "Select tables optimized away";
unknown's avatar
unknown committed
611
      tables_list= 0;				// All tables resolved
unknown's avatar
unknown committed
612 613
    }
  }
614
  if (!tables_list)
615
  {
616
    DBUG_PRINT("info",("No tables"));
617
    error= 0;
618
    DBUG_RETURN(0);
619
  }
unknown's avatar
unknown committed
620
  error= -1;					// Error is sent to client
621
  sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables);
unknown's avatar
unknown committed
622 623

  /* Calculate how to do the join */
624
  thd->proc_info= "statistics";
625
  if (make_join_statistics(this, select_lex->leaf_tables, conds, &keyuse) ||
626
      thd->is_fatal_error)
627 628
  {
    DBUG_PRINT("error",("Error: make_join_statistics() failed"));
unknown's avatar
unknown committed
629
    DBUG_RETURN(1);
630
  }
631

unknown's avatar
unknown committed
632 633
  /* Remove distinct if only const tables */
  select_distinct= select_distinct && (const_tables != tables);
634
  thd->proc_info= "preparing";
unknown's avatar
unknown committed
635
  if (result->initialize_tables(this))
unknown's avatar
unknown committed
636
  {
637 638
    DBUG_PRINT("error",("Error: initialize_tables() failed"));
    DBUG_RETURN(1);				// error == -1
unknown's avatar
unknown committed
639
  }
640
  if (const_table_map != found_const_table_map &&
unknown's avatar
af  
unknown committed
641 642 643 644
      !(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
645
  {
unknown's avatar
unknown committed
646
    zero_result_cause= "no matching row in const table";
647 648
    DBUG_PRINT("error",("Error: %s", zero_result_cause));
    error= 0;
649
    DBUG_RETURN(0);
unknown's avatar
unknown committed
650 651
  }
  if (!(thd->options & OPTION_BIG_SELECTS) &&
unknown's avatar
unknown committed
652
      best_read > (double) thd->variables.max_join_size &&
unknown's avatar
unknown committed
653 654
      !(select_options & SELECT_DESCRIBE))
  {						/* purecov: inspected */
655
    my_message(ER_TOO_BIG_SELECT, ER(ER_TOO_BIG_SELECT), MYF(0));
unknown's avatar
unknown committed
656
    error= 1;					/* purecov: inspected */
unknown's avatar
unknown committed
657
    DBUG_RETURN(1);
unknown's avatar
unknown committed
658
  }
659
  if (const_tables && !thd->locked_tables &&
unknown's avatar
unknown committed
660
      !(select_options & SELECT_NO_UNLOCK))
661
    mysql_unlock_some_tables(thd, table, const_tables);
662
  if (!conds && outer_join)
663 664 665 666
  {
    /* Handle the case where we have an OUTER JOIN without a WHERE */
    conds=new Item_int((longlong) 1,1);	// Always true
  }
667
  select=make_select(*table, const_table_map,
668
		     const_table_map, conds, &error, true);
unknown's avatar
unknown committed
669
  if (error)
unknown's avatar
unknown committed
670 671
  {						/* purecov: inspected */
    error= -1;					/* purecov: inspected */
672
    DBUG_PRINT("error",("Error: make_select() failed"));
unknown's avatar
unknown committed
673
    DBUG_RETURN(1);
unknown's avatar
unknown committed
674
  }
675 676 677

  make_outerjoin_info(this);

unknown's avatar
unknown committed
678 679 680 681 682 683 684 685 686 687
  /*
    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
688
    DBUG_EXECUTE("where", print_where(conds, "after substitute_best_equal"););
unknown's avatar
unknown committed
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
  }
  /*
    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();
    }
  }

705
  if (make_join_select(this, select, conds))
unknown's avatar
unknown committed
706
  {
707 708
    zero_result_cause=
      "Impossible WHERE noticed after reading const tables";
709
    DBUG_RETURN(0);				// error == 0
unknown's avatar
unknown committed
710 711 712 713 714
  }

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

  /* Optimize distinct away if possible */
unknown's avatar
unknown committed
715 716
  {
    ORDER *org_order= order;
unknown's avatar
unknown committed
717
    order=remove_const(this, order,conds,&simple_order);
unknown's avatar
unknown committed
718 719 720 721 722 723 724
    /*
      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;
  }
725
  if (group_list || tmp_table_param.sum_func_count)
unknown's avatar
unknown committed
726 727 728 729
  {
    if (! hidden_group_fields)
      select_distinct=0;
  }
unknown's avatar
unknown committed
730
  else if (select_distinct && tables - const_tables == 1)
unknown's avatar
unknown committed
731
  {
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
    /*
      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
747
    JOIN_TAB *tab= &join_tab[const_tables];
748 749 750
    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
751 752
    if ((group_list=create_distinct_group(thd, order, fields_list,
				          &all_order_fields_used)))
753 754
    {
      bool skip_group= (skip_sort_order &&
unknown's avatar
unknown committed
755
			test_if_skip_sort_order(tab, group_list, select_limit,
756 757 758 759 760 761 762 763 764
						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)
765 766 767 768 769 770
	{
	  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
771
	    */
unknown's avatar
unknown committed
772
	    tmp_table_param.quick_group=0;
773
	  }
774
	  order=0;
unknown's avatar
unknown committed
775
        }
unknown's avatar
unknown committed
776
	group=1;				// For end_write_group
777 778
      }
      else
unknown's avatar
unknown committed
779
	group_list= 0;
unknown's avatar
unknown committed
780
    }
781
    else if (thd->is_fatal_error)			// End of memory
unknown's avatar
unknown committed
782
      DBUG_RETURN(1);
unknown's avatar
unknown committed
783
  }
784 785 786
  simple_group= 0;
  if (rollup.state == ROLLUP::STATE_NONE)
    group_list= remove_const(this, group_list, conds, &simple_group);
787
  if (!group_list && group)
unknown's avatar
unknown committed
788 789 790 791 792
  {
    order=0;					// The output has only one row
    simple_order=1;
  }

793 794
  calc_group_buffer(this, group_list);
  send_group_parts= tmp_table_param.group_parts; /* Save org parts */
unknown's avatar
unknown committed
795 796
  if (procedure && procedure->group)
  {
797 798 799
    group_list= procedure->group= remove_const(this, procedure->group, conds,
					       &simple_group);
    calc_group_buffer(this, group_list);
unknown's avatar
unknown committed
800 801
  }

802 803
  if (test_if_subpart(group_list, order) ||
      (!group_list && tmp_table_param.sum_func_count))
unknown's avatar
unknown committed
804 805
    order=0;

unknown's avatar
unknown committed
806
  // Can't use sort on head table if using row cache
807
  if (full_join)
unknown's avatar
unknown committed
808
  {
809
    if (group_list)
unknown's avatar
unknown committed
810 811 812 813 814
      simple_group=0;
    if (order)
      simple_order=0;
  }

815 816 817 818 819 820 821 822 823
  /*
    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.
  */
824
  need_tmp= (const_tables != tables &&
unknown's avatar
unknown committed
825
	     ((select_distinct || !simple_order || !simple_group) ||
unknown's avatar
unknown committed
826
	      (group_list && order) ||
827
	      test(select_options & OPTION_BUFFER_RESULT)));
unknown's avatar
unknown committed
828

unknown's avatar
unknown committed
829
  // No cache for MATCH
830
  make_join_readinfo(this,
unknown's avatar
unknown committed
831
		     (select_options & (SELECT_DESCRIBE |
832
					SELECT_NO_JOIN_CACHE)) |
unknown's avatar
unknown committed
833
		     (select_lex->ftfunc_list->elements ?
834
		      SELECT_NO_JOIN_CACHE : 0));
unknown's avatar
unknown committed
835

836 837 838 839
  /* Perform FULLTEXT search before all regular searches */
  if (!(select_options & SELECT_DESCRIBE))
    init_ftfuncs(thd, select_lex, test(order));

840 841 842
  /*
    is this simple IN subquery?
  */
843
  if (!group_list && !order &&
844
      unit->item && unit->item->substype() == Item_subselect::IN_SUBS &&
845
      tables == 1 && conds &&
846 847
      !unit->first_select()->next_select())
  {
848
    if (!having)
849
    {
850
      Item *where= 0;
851 852
      if (join_tab[0].type == JT_EQ_REF &&
	  join_tab[0].ref.items[0]->name == in_left_expr_name)
853
      {
854 855
	if (test_in_subselect(&where))
	{
856
	  join_tab[0].type= JT_UNIQUE_SUBQUERY;
857 858
	  error= 0;
	  DBUG_RETURN(unit->item->
859 860 861 862 863
		      change_engine(new
				    subselect_uniquesubquery_engine(thd,
								    join_tab,
								    unit->item,
								    where)));
864
	}
865
      }
866 867
      else if (join_tab[0].type == JT_REF &&
	       join_tab[0].ref.items[0]->name == in_left_expr_name)
868
      {
869 870
	if (test_in_subselect(&where))
	{
871
	  join_tab[0].type= JT_INDEX_SUBQUERY;
872 873
	  error= 0;
	  DBUG_RETURN(unit->item->
874 875 876 877 878 879
		      change_engine(new
				    subselect_indexsubquery_engine(thd,
								   join_tab,
								   unit->item,
								   where,
								   0)));
880
	}
881
      }
882
    } else if (join_tab[0].type == JT_REF_OR_NULL &&
883
	       join_tab[0].ref.items[0]->name == in_left_expr_name &&
884 885 886 887
	       having->type() == Item::FUNC_ITEM &&
	       ((Item_func *) having)->functype() ==
	       Item_func::ISNOTNULLTEST_FUNC)
    {
888
      join_tab[0].type= JT_INDEX_SUBQUERY;
889
      error= 0;
890 891 892 893 894

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

896
      DBUG_RETURN(unit->item->
897 898 899 900 901
		  change_engine(new subselect_indexsubquery_engine(thd,
								   join_tab,
								   unit->item,
								   conds,
								   1)));
902
    }
903

904
  }
905 906 907 908 909 910 911
  /*
    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
912 913

#ifdef HAVE_INNOBASE_DB
914
  if (need_tmp || select_distinct || group_list || order)
unknown's avatar
unknown committed
915
  {
916
    for (uint i_h = const_tables; i_h < tables; i_h++)
unknown's avatar
unknown committed
917
    {
918
      TABLE* table_h = join_tab[i_h].table;
unknown's avatar
af  
unknown committed
919
      table_h->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
unknown's avatar
unknown committed
920 921 922 923
    }
  }
#endif

924
  DBUG_EXECUTE("info",TEST_join(this););
unknown's avatar
unknown committed
925 926 927 928 929
  /*
    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.
930
  */
931
  if (const_tables != tables &&
932
      (order || group_list) &&
unknown's avatar
af  
unknown committed
933
      join_tab[const_tables].type != JT_ALL &&
934
      join_tab[const_tables].type != JT_FT &&
unknown's avatar
af  
unknown committed
935
      join_tab[const_tables].type != JT_REF_OR_NULL &&
936
      (order && simple_order || group_list && simple_group))
unknown's avatar
unknown committed
937
  {
938
    if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
unknown's avatar
unknown committed
939
      DBUG_RETURN(1);
unknown's avatar
unknown committed
940 941 942
  }

  if (!(select_options & SELECT_BIG_RESULT) &&
943
      ((group_list && const_tables != tables &&
944
	(!simple_group ||
945
	 !test_if_skip_sort_order(&join_tab[const_tables], group_list,
946
				  unit->select_limit_cnt, 0))) ||
unknown's avatar
unknown committed
947
       select_distinct) &&
948
      tmp_table_param.quick_group && !procedure)
unknown's avatar
unknown committed
949 950 951
  {
    need_tmp=1; simple_order=simple_group=0;	// Force tmp table without sort
  }
952

unknown's avatar
unknown committed
953
  tmp_having= having;
954
  if (select_options & SELECT_DESCRIBE)
955 956
  {
    error= 0;
957
    DBUG_RETURN(0);
958
  }
959 960 961 962 963 964 965 966 967
  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();
968

969 970 971 972 973 974 975 976 977 978 979
    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 :
980 981
			   HA_POS_ERROR,
			   (char *) "")))
982
      DBUG_RETURN(1);
983 984 985 986 987 988 989 990 991 992 993

    /*
      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
994
    if (tmp_having && 
995 996 997 998 999 1000 1001 1002
	(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";
1003
      if (create_sort_index(thd, this, group_list,
1004
			    HA_POS_ERROR, HA_POS_ERROR) ||
1005
	  alloc_group_fields(this, group_list) ||
1006 1007
          make_sum_func_list(all_fields, fields_list, 1) ||
          setup_sum_funcs(thd, sum_funcs))
1008 1009 1010 1011 1012
	DBUG_RETURN(1);
      group_list=0;
    }
    else
    {
1013 1014
      if (make_sum_func_list(all_fields, fields_list, 0) ||
          setup_sum_funcs(thd, sum_funcs))
1015 1016 1017 1018 1019
	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";
1020
	if (create_sort_index(thd, this, order,
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
                              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;
1036
      JOIN_TAB *last_join_tab= join_tab+tables-1;
1037 1038
      do
      {
1039
	if (used_tables & last_join_tab->table->map)
1040
	  break;
1041 1042
	last_join_tab->not_used_in_distinct=1;
      } while (last_join_tab-- != join_tab);
1043 1044 1045 1046
      /* Optimize "select distinct b from t1 order by key_part_1 limit #" */
      if (order && skip_sort_order)
      {
 	/* Should always succeed */
1047
	if (test_if_skip_sort_order(&join_tab[const_tables],
1048 1049 1050 1051 1052
				    order, unit->select_limit_cnt, 0))
	  order=0;
      }
    }
    
unknown's avatar
unknown committed
1053
    if (select_lex->master_unit()->uncacheable)
1054 1055 1056
    {
      if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
	DBUG_RETURN(-1);
1057
      error= 0;				// Ensure that tmp_join.error= 0
1058 1059 1060 1061
      restore_tmp();
    }
  }

1062
  error= 0;
1063 1064 1065
  DBUG_RETURN(0);
}

1066

1067
/*
1068
  Restore values in temporary join
1069
*/
1070
void JOIN::restore_tmp()
1071
{
1072
  memcpy(tmp_join, this, (size_t) sizeof(JOIN));
1073 1074
}

1075

1076 1077 1078 1079
int
JOIN::reinit()
{
  DBUG_ENTER("JOIN::reinit");
1080
  /* TODO move to unit reinit */
unknown's avatar
af  
unknown committed
1081
  unit->set_limit(select_lex, select_lex);
unknown's avatar
VIEW  
unknown committed
1082 1083 1084 1085 1086

  /* conds should not be used here, it is added just for safety */
  if (tables_list)
  {
    tables_list->setup_is_done= 0;
unknown's avatar
unknown committed
1087 1088
    if (setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables,
                     TRUE, FALSE))
unknown's avatar
VIEW  
unknown committed
1089 1090 1091
      DBUG_RETURN(1);
  }

1092
  /* Reset of sum functions */
unknown's avatar
unknown committed
1093
  first_record= 0;
unknown's avatar
unknown committed
1094

1095 1096 1097 1098 1099
  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
1100
    filesort_free_buffers(exec_tmp_table1);
1101 1102 1103 1104 1105 1106
  }
  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
1107
    filesort_free_buffers(exec_tmp_table2);
1108 1109
  }
  if (items0)
1110
    set_items_ref_array(items0);
1111

1112 1113 1114
  if (join_tab_save)
    memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * tables);

1115 1116 1117
  if (tmp_join)
    restore_tmp();

unknown's avatar
af  
unknown committed
1118 1119 1120 1121 1122 1123 1124
  if (sum_funcs)
  {
    Item_sum *func, **func_ptr= sum_funcs;
    while ((func= *(func_ptr++)))
      func->clear();
  }

1125 1126 1127
  DBUG_RETURN(0);
}

1128 1129 1130 1131

bool
JOIN::save_join_tab()
{
unknown's avatar
unknown committed
1132
  if (!join_tab_save && select_lex->master_unit()->uncacheable)
1133
  {
unknown's avatar
unknown committed
1134 1135
    if (!(join_tab_save= (JOIN_TAB*)thd->memdup((gptr) join_tab,
						sizeof(JOIN_TAB) * tables)))
1136 1137 1138 1139 1140 1141
      return 1;
  }
  return 0;
}


1142
/*
1143
  Exec select
1144 1145 1146 1147 1148 1149
*/
void
JOIN::exec()
{
  int      tmp_error;
  DBUG_ENTER("JOIN::exec");
unknown's avatar
unknown committed
1150
  
1151
  error= 0;
unknown's avatar
unknown committed
1152 1153 1154 1155
  if (procedure)
  {
    if (procedure->change_columns(fields_list) ||
	result->prepare(fields_list, unit))
1156 1157
    {
      thd->limit_found_rows= thd->examined_row_count= 0;
unknown's avatar
unknown committed
1158
      DBUG_VOID_RETURN;
1159
    }
unknown's avatar
unknown committed
1160
  }
1161

unknown's avatar
unknown committed
1162
  if (!tables_list)
1163 1164
  {                                           // Only test of functions
    if (select_options & SELECT_DESCRIBE)
unknown's avatar
af  
unknown committed
1165
      select_describe(this, FALSE, FALSE, FALSE,
unknown's avatar
unknown committed
1166
		      (zero_result_cause?zero_result_cause:"No tables used"));
1167 1168
    else
    {
1169 1170
      result->send_fields(fields_list,
                          Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
1171 1172
      if (!having || having->val_int())
      {
1173 1174 1175
	if (do_send_rows && (procedure ? (procedure->send_row(fields_list) ||
                                          procedure->end_of_records())
                                       : result->send_data(fields_list)))
unknown's avatar
unknown committed
1176
	  error= 1;
1177
	else
1178
	{
unknown's avatar
unknown committed
1179
	  error= (int) result->send_eof();
1180 1181
	  send_records=1;
	}
1182 1183
      }
      else
1184
	error=(int) result->send_eof();
1185
    }
1186
    thd->limit_found_rows= thd->examined_row_count= 0;
1187 1188
    DBUG_VOID_RETURN;
  }
1189
  thd->limit_found_rows= thd->examined_row_count= 0;
1190 1191 1192

  if (zero_result_cause)
  {
1193
    (void) return_zero_rows(this, result, select_lex->leaf_tables, fields_list,
unknown's avatar
af  
unknown committed
1194
			    send_row_on_empty_set(),
unknown's avatar
unknown committed
1195 1196
			    select_options,
			    zero_result_cause,
1197
			    having, procedure,
unknown's avatar
unknown committed
1198
			    unit);
1199 1200 1201
    DBUG_VOID_RETURN;
  }

unknown's avatar
unknown committed
1202 1203
  if (select_options & SELECT_DESCRIBE)
  {
unknown's avatar
unknown committed
1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
    /*
      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
1219
    if (order &&
1220
	(const_tables == tables ||
unknown's avatar
unknown committed
1221
 	 ((simple_order || skip_sort_order) &&
1222
	  test_if_skip_sort_order(&join_tab[const_tables], order,
1223
				  select_limit, 0))))
unknown's avatar
unknown committed
1224
      order=0;
1225
    having= tmp_having;
1226
    select_describe(this, need_tmp,
1227
		    order != 0 && !skip_sort_order,
unknown's avatar
unknown committed
1228
		    select_distinct);
1229
    DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1230 1231
  }

1232 1233 1234 1235
  JOIN *curr_join= this;
  List<Item> *curr_all_fields= &all_fields;
  List<Item> *curr_fields_list= &fields_list;
  TABLE *curr_tmp_table= 0;
1236

1237 1238 1239 1240 1241 1242
  if ((curr_join->select_lex->options & OPTION_SCHEMA_TABLE) &&
      get_schema_tables_result(curr_join))
  {
    DBUG_VOID_RETURN;
  }

unknown's avatar
unknown committed
1243 1244 1245
  /* Create a tmp table if distinct or if the sort is too complicated */
  if (need_tmp)
  {
1246 1247 1248
    if (tmp_join)
      curr_join= tmp_join;
    curr_tmp_table= exec_tmp_table1;
unknown's avatar
unknown committed
1249 1250

    /* Copy data to the temporary table */
1251
    thd->proc_info= "Copying to tmp table";
1252 1253
    
    if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
1254
    {
1255 1256
      error= tmp_error;
      DBUG_VOID_RETURN;
1257
    }
1258 1259 1260 1261 1262
    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
1263
    /* Change sum_fields reference to calculated fields in tmp_table */
1264 1265
    curr_join->all_fields= *curr_all_fields;
    if (!items1)
unknown's avatar
unknown committed
1266
    {
1267 1268 1269
      items1= items0 + all_fields.elements;
      if (sort_and_group || curr_tmp_table->group)
      {
1270
	if (change_to_use_tmp_fields(thd, items1,
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287
				     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;
1288
    set_items_ref_array(items1);
1289 1290 1291 1292 1293 1294 1295 1296
    
    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
1297 1298 1299
    }
    else
    {
1300 1301 1302
      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
1303
    }
1304 1305
    
    // procedure can't be used inside subselect => we do nothing special for it
unknown's avatar
unknown committed
1306 1307
    if (procedure)
      procedure->update_refs();
1308 1309
    
    if (curr_tmp_table->group)
unknown's avatar
unknown committed
1310
    {						// Already grouped
unknown's avatar
unknown committed
1311
      if (!curr_join->order && !curr_join->no_order && !skip_sort_order)
1312 1313
	curr_join->order= curr_join->group_list;  /* order by group */
      curr_join->group_list= 0;
unknown's avatar
unknown committed
1314
    }
1315
    
unknown's avatar
unknown committed
1316
    /*
1317 1318 1319 1320 1321
      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
1322 1323
    */

1324 1325 1326 1327 1328
    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
1329 1330
    {					/* Must copy to another table */
      DBUG_PRINT("info",("Creating group table"));
1331
      
unknown's avatar
unknown committed
1332
      /* Free first data from old join */
1333
      curr_join->join_free(0);
1334
      if (make_simple_join(curr_join, curr_tmp_table))
unknown's avatar
unknown committed
1335
	DBUG_VOID_RETURN;
1336
      calc_group_buffer(curr_join, group_list);
1337 1338
      count_field_types(&curr_join->tmp_table_param,
			curr_join->tmp_all_fields1,
1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
			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,
1358 1359
						HA_POS_ERROR,
						(char *) "")))
1360 1361 1362
	  DBUG_VOID_RETURN;
	curr_join->exec_tmp_table2= exec_tmp_table2;
      }
1363
      if (curr_join->group_list)
unknown's avatar
unknown committed
1364
      {
1365
	thd->proc_info= "Creating sort index";
1366 1367 1368 1369
	if (curr_join->join_tab == join_tab && save_join_tab())
	{
	  DBUG_VOID_RETURN;
	}
1370
	if (create_sort_index(thd, curr_join, curr_join->group_list,
1371
			      HA_POS_ERROR, HA_POS_ERROR) ||
1372
	    make_group_fields(this, curr_join))
unknown's avatar
unknown committed
1373
	{
1374
	  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1375
	}
1376
	curr_join->group_list= 0;
unknown's avatar
unknown committed
1377
      }
1378
      
unknown's avatar
unknown committed
1379
      thd->proc_info="Copying to group table";
1380
      tmp_error= -1;
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
      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;
	}
      }
1395
      if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1396
					1, TRUE) ||
1397
          setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
1398 1399
	  (tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
				0)))
unknown's avatar
unknown committed
1400
      {
1401
	error= tmp_error;
1402
	DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1403
      }
1404 1405 1406 1407 1408 1409 1410 1411
      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;
1412
	if (change_to_use_tmp_fields(thd, items2,
1413 1414 1415 1416 1417 1418 1419 1420
				     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;
1421
      set_items_ref_array(items2);
1422 1423 1424 1425 1426 1427 1428
      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 */
    
1429
    curr_join->join_free(0);			/* Free quick selects */
1430
    if (select_distinct && ! group_list)
unknown's avatar
unknown committed
1431 1432
    {
      thd->proc_info="Removing duplicates";
1433 1434 1435 1436
      if (curr_join->tmp_having)
	curr_join->tmp_having->update_used_tables();
      if (remove_duplicates(curr_join, curr_tmp_table,
			    curr_join->fields_list, curr_join->tmp_having))
1437
	DBUG_VOID_RETURN;
1438 1439
      curr_join->tmp_having=0;
      curr_join->select_distinct=0;
unknown's avatar
unknown committed
1440
    }
1441 1442
    curr_tmp_table->reginfo.lock_type= TL_UNLOCK;
    if (make_simple_join(curr_join, curr_tmp_table))
1443
      DBUG_VOID_RETURN;
1444 1445 1446
    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
1447 1448
  }
  if (procedure)
1449 1450 1451
    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
1452 1453
      (procedure && (procedure->flags & PROC_GROUP)))
  {
1454 1455 1456 1457
    if (make_group_fields(this, curr_join))
    {
      DBUG_VOID_RETURN;
    }
1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481
    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;
1482
    set_items_ref_array(items3);
1483

1484
    if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1485 1486 1487
				      1, TRUE) || 
        setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
        thd->is_fatal_error)
1488
      DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1489
  }
1490
  if (curr_join->group_list || curr_join->order)
unknown's avatar
unknown committed
1491 1492 1493 1494
  {
    DBUG_PRINT("info",("Sorting for send_fields"));
    thd->proc_info="Sorting result";
    /* If we have already done the group, add HAVING to sorted table */
1495 1496
    if (curr_join->tmp_having && ! curr_join->group_list && 
	! curr_join->sort_and_group)
unknown's avatar
unknown committed
1497
    {
1498 1499
      // Some tables may have been const
      curr_join->tmp_having->update_used_tables();
1500 1501 1502
      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
1503

1504 1505
      Item* sort_table_cond= make_cond_for_table(curr_join->tmp_having,
						 used_tables,
1506
						 used_tables);
unknown's avatar
unknown committed
1507 1508
      if (sort_table_cond)
      {
1509 1510
	if (!curr_table->select)
	  if (!(curr_table->select= new SQL_SELECT))
1511
	    DBUG_VOID_RETURN;
1512 1513
	if (!curr_table->select->cond)
	  curr_table->select->cond= sort_table_cond;
unknown's avatar
unknown committed
1514
	else					// This should never happen
unknown's avatar
af  
unknown committed
1515
	{
1516
	  if (!(curr_table->select->cond=
unknown's avatar
af  
unknown committed
1517 1518
		new Item_cond_and(curr_table->select->cond,
				  sort_table_cond)))
1519
	    DBUG_VOID_RETURN;
unknown's avatar
af  
unknown committed
1520 1521 1522 1523 1524 1525
	  /*
	    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();
	}
1526
	curr_table->select_cond= curr_table->select->cond;
1527 1528
	curr_table->select_cond->top_level_item();
	DBUG_EXECUTE("where",print_where(curr_table->select->cond,
unknown's avatar
unknown committed
1529
					 "select and having"););
1530 1531 1532
	curr_join->tmp_having= make_cond_for_table(curr_join->tmp_having,
						   ~ (table_map) 0,
						   ~used_tables);
unknown's avatar
unknown committed
1533 1534 1535
	DBUG_EXECUTE("where",print_where(conds,"having after sort"););
      }
    }
unknown's avatar
unknown committed
1536
    {
unknown's avatar
unknown committed
1537
      if (group)
1538
	curr_join->select_limit= HA_POS_ERROR;
unknown's avatar
unknown committed
1539
      else
unknown's avatar
unknown committed
1540
      {
unknown's avatar
unknown committed
1541 1542 1543 1544
	/*
	  We can abort sorting after thd->select_limit rows if we there is no
	  WHERE clause for any tables after the sorted one.
	*/
1545
	JOIN_TAB *curr_table= &curr_join->join_tab[curr_join->const_tables+1];
1546
	JOIN_TAB *end_table= &curr_join->join_tab[tables];
1547
	for (; curr_table < end_table ; curr_table++)
unknown's avatar
unknown committed
1548
	{
unknown's avatar
unknown committed
1549 1550 1551 1552
	  /*
	    table->keyuse is set in the case there was an original WHERE clause
	    on the table that was optimized away.
	  */
1553
	  if (curr_table->select_cond ||
1554
	      (curr_table->keyuse && !curr_table->first_inner))
unknown's avatar
unknown committed
1555 1556
	  {
	    /* We have to sort all rows */
1557
	    curr_join->select_limit= HA_POS_ERROR;
unknown's avatar
unknown committed
1558 1559
	    break;
	  }
unknown's avatar
unknown committed
1560 1561
	}
      }
1562 1563 1564 1565
      if (curr_join->join_tab == join_tab && save_join_tab())
      {
	DBUG_VOID_RETURN;
      }
unknown's avatar
unknown committed
1566 1567 1568 1569 1570 1571 1572 1573 1574
      /*
	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.
      */
1575
      if (create_sort_index(thd, curr_join,
1576 1577
			    curr_join->group_list ? 
			    curr_join->group_list : curr_join->order,
unknown's avatar
unknown committed
1578 1579 1580
			    curr_join->select_limit,
			    (select_options & OPTION_FOUND_ROWS ?
			     HA_POS_ERROR : unit->select_limit_cnt)))
1581
	DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1582
    }
unknown's avatar
unknown committed
1583
  }
1584 1585 1586 1587 1588 1589
  /* 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;
  }
1590
  curr_join->having= curr_join->tmp_having;
1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622
  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";
    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;
  }

1623 1624
  DBUG_VOID_RETURN;
}
unknown's avatar
unknown committed
1625

1626

1627 1628 1629 1630 1631
/*
  Clean up join. Return error that hold JOIN.
*/

int
1632
JOIN::cleanup()
1633
{
1634
  DBUG_ENTER("JOIN::cleanup");
1635 1636 1637
  select_lex->join= 0;

  if (tmp_join)
unknown's avatar
unknown committed
1638 1639 1640 1641 1642 1643
  {
    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
1644
	tab->cleanup();
unknown's avatar
unknown committed
1645 1646 1647
      }
    }
    tmp_join->tmp_join= 0;
unknown's avatar
unknown committed
1648
    tmp_table_param.copy_field=0;
1649
    DBUG_RETURN(tmp_join->cleanup());
unknown's avatar
unknown committed
1650
  }
unknown's avatar
unknown committed
1651
  cond_equal= 0;
1652

1653
  lock=0;                                     // It's faster to unlock later
1654
  join_free(1);
unknown's avatar
af  
unknown committed
1655 1656 1657 1658
  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
1659 1660 1661
  delete select;
  delete_dynamic(&keyuse);
  delete procedure;
1662 1663 1664
  for (SELECT_LEX_UNIT *lex_unit= select_lex->first_inner_unit();
       lex_unit != 0;
       lex_unit= lex_unit->next_unit())
1665
  {
1666
    error|= lex_unit->cleanup();
1667 1668
  }
  DBUG_RETURN(error);
1669 1670
}

1671

1672 1673 1674 1675 1676 1677 1678 1679
/************************* 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
1680 1681 1682

    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()
1683
  */
unknown's avatar
unknown committed
1684 1685 1686
  main_mem_root=  *thd->mem_root;
  /* Allocate new memory root for thd */
  init_sql_alloc(thd->mem_root,
1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699
                 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
1700
  free_list=	  thd->free_list;
1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743
  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
1744
  DBUG_ENTER("Cursor::open");
1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765

  /*
    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. */

  Next_select_func end_select= join->sort_and_group || join->procedure &&
    join->procedure->flags & PROC_GROUP ?
    end_send_group : end_send;

  join->join_tab[join->tables-1].next_select= end_select;
  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
1766 1767 1768
  for (JOIN_TAB *tab= join_tab;
       tab != join->join_tab + join->tables - 1;
       tab++)
1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781
  {
    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);

unknown's avatar
unknown committed
1782
  DBUG_RETURN(join_tab->read_first_record(join_tab));
1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800
}


/*
  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
1801
  JOIN_TAB *join_tab= join->join_tab + join->const_tables;
unknown's avatar
unknown committed
1802
  COND *on_expr= *join_tab->on_expr_ref;
1803 1804 1805 1806
  COND *select_cond= join_tab->select_cond;
  READ_RECORD *info= &join_tab->read_record;
  int error= 0;

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

1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824
  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
1825
      my_message(ER_SERVER_SHUTDOWN, ER(ER_SERVER_SHUTDOWN), MYF(0));
1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873
      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;

1874 1875
  if (error == -3)                              /* LIMIT clause worked */
    error= 0;
1876

1877
#ifdef USING_TRANSACTIONS
unknown's avatar
unknown committed
1878
    ha_release_temporary_latches(thd);
1879 1880 1881 1882 1883 1884
#endif

  thd->restore_backup_item_arena(this, &thd->stmt_backup);
  if (error == -4)
  {
    /* Fetch limit worked, possibly more rows are there */
1885 1886 1887
    thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
    ::send_eof(thd);
    thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
1888 1889 1890
  }
  else
  {
1891
    close();
1892 1893 1894 1895 1896 1897 1898
    if (error == 0)
    {
      thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
      ::send_eof(thd);
      thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
    }
    else
1899
      my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
1900 1901 1902
    /* free cursor memory */
    free_items(free_list);
    free_list= 0;
unknown's avatar
unknown committed
1903
    free_root(&main_mem_root, MYF(0));
1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940
  }
  return error;
}


void
Cursor::close()
{
  THD *thd= join->thd;
  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_open_tables= thd->open_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;
  }
1941 1942
  join= 0;
  unit= 0;
1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954
}


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
1955
  free_root(&main_mem_root, MYF(0));
1956 1957 1958 1959 1960
}

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


unknown's avatar
unknown committed
1961
bool
1962
mysql_select(THD *thd, Item ***rref_pointer_array,
unknown's avatar
unknown committed
1963
	     TABLE_LIST *tables, uint wild_num, List<Item> &fields,
1964 1965 1966
	     COND *conds, uint og_num,  ORDER *order, ORDER *group,
	     Item *having, ORDER *proc_param, ulong select_options,
	     select_result *result, SELECT_LEX_UNIT *unit,
1967
	     SELECT_LEX *select_lex)
1968
{
unknown's avatar
unknown committed
1969
  bool err;
unknown's avatar
unknown committed
1970
  bool free_join= 1;
1971 1972
  DBUG_ENTER("mysql_select");

unknown's avatar
unknown committed
1973
  JOIN *join;
1974
  if (select_lex->join != 0)
1975
  {
unknown's avatar
unknown committed
1976
    join= select_lex->join;
unknown's avatar
unknown committed
1977 1978 1979 1980
    /*
      is it single SELECT in derived table, called in derived table
      creation
    */
1981 1982
    if (select_lex->linkage != DERIVED_TABLE_TYPE ||
	(select_options & SELECT_DESCRIBE))
unknown's avatar
unknown committed
1983
    {
1984
      if (select_lex->linkage != GLOBAL_OPTIONS_TYPE)
1985
      {
1986
	//here is EXPLAIN of subselect or derived table
unknown's avatar
af  
unknown committed
1987
	if (join->change_result(result))
1988
	{
unknown's avatar
unknown committed
1989
	  DBUG_RETURN(TRUE);
1990
	}
1991
      }
1992
      else
1993
      {
1994 1995 1996 1997 1998 1999
	if (join->prepare(rref_pointer_array, tables, wild_num,
			  conds, og_num, order, group, having, proc_param,
			  select_lex, unit))
	{
	  goto err;
	}
2000
      }
unknown's avatar
unknown committed
2001
    }
unknown's avatar
af  
unknown committed
2002
    free_join= 0;
unknown's avatar
unknown committed
2003
    join->select_options= select_options;
2004
  }
unknown's avatar
unknown committed
2005 2006
  else
  {
unknown's avatar
af  
unknown committed
2007
    if (!(join= new JOIN(thd, fields, select_options, result)))
unknown's avatar
unknown committed
2008
	DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
2009 2010
    thd->proc_info="init";
    thd->used_tables=0;                         // Updated by setup_fields
2011 2012
    if (join->prepare(rref_pointer_array, tables, wild_num,
		      conds, og_num, order, group, having, proc_param,
2013
		      select_lex, unit))
unknown's avatar
unknown committed
2014
    {
2015
      goto err;
unknown's avatar
unknown committed
2016 2017 2018
    }
  }

unknown's avatar
unknown committed
2019
  if ((err= join->optimize()))
unknown's avatar
unknown committed
2020
  {
unknown's avatar
unknown committed
2021 2022
    goto err;					// 1
  }
2023

unknown's avatar
unknown committed
2024
  if (thd->lex->describe & DESCRIBE_EXTENDED)
unknown's avatar
unknown committed
2025 2026 2027 2028 2029
  {
    join->conds_history= join->conds;
    join->having_history= (join->having?join->having:join->tmp_having);
  }

2030
  if (thd->net.report_error)
2031 2032 2033 2034
    goto err;

  join->exec();

2035 2036 2037 2038 2039 2040 2041 2042 2043 2044
  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
2045
  if (thd->lex->describe & DESCRIBE_EXTENDED)
unknown's avatar
unknown committed
2046 2047 2048 2049 2050
  {
    select_lex->where= join->conds_history;
    select_lex->having= join->having_history;
  }

2051
err:
unknown's avatar
unknown committed
2052 2053 2054
  if (free_join)
  {
    thd->proc_info="end";
2055
    err= join->cleanup();
unknown's avatar
unknown committed
2056
    delete join;
unknown's avatar
unknown committed
2057
    DBUG_RETURN(err || thd->net.report_error);
unknown's avatar
unknown committed
2058
  }
unknown's avatar
unknown committed
2059
  DBUG_RETURN(join->error);
unknown's avatar
unknown committed
2060 2061 2062
}

/*****************************************************************************
2063 2064
  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
2065 2066
*****************************************************************************/

2067 2068
static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
				      TABLE *table,
unknown's avatar
unknown committed
2069
				      const key_map *keys,ha_rows limit)
unknown's avatar
unknown committed
2070 2071 2072 2073 2074 2075 2076
{
  int error;
  DBUG_ENTER("get_quick_record_count");
  if (select)
  {
    select->head=table;
    table->reginfo.impossible_range=0;
unknown's avatar
af  
unknown committed
2077 2078
    if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,
					 limit)) == 1)
unknown's avatar
unknown committed
2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090
      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 */
}


2091 2092 2093 2094 2095 2096 2097
/*
  Calculate the best possible join and initialize the join structure

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

unknown's avatar
unknown committed
2099
static bool
2100
make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
2101
		     DYNAMIC_ARRAY *keyuse_array)
unknown's avatar
unknown committed
2102 2103
{
  int error;
2104
  TABLE *table;
2105 2106 2107
  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
2108 2109 2110 2111 2112 2113 2114 2115
  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;
2116 2117
  stat=(JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB)*table_count);
  stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)*MAX_TABLES);
2118
  table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*(table_count*2));
unknown's avatar
unknown committed
2119 2120 2121 2122 2123 2124
  if (!stat || !stat_ref || !table_vector)
    DBUG_RETURN(1);				// Eom /* purecov: inspected */

  join->best_ref=stat_vector;

  stat_end=stat+table_count;
2125
  found_const_table_map= all_table_map=0;
unknown's avatar
unknown committed
2126 2127
  const_count=0;

unknown's avatar
VIEW  
unknown committed
2128 2129
  for (s= stat, i= 0;
       tables;
2130
       s++, tables= tables->next_leaf, i++)
unknown's avatar
unknown committed
2131
  {
2132
    TABLE_LIST *embedding= tables->embedding;
unknown's avatar
unknown committed
2133
    stat_vector[i]=s;
2134 2135 2136 2137
    s->keys.init();
    s->const_keys.init();
    s->checked_keys.init();
    s->needed_reg.init();
unknown's avatar
unknown committed
2138
    table_vector[i]=s->table=table=tables->table;
2139
    table->pos_in_table_list= tables;
unknown's avatar
unknown committed
2140
    table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);// record count
2141
    table->quick_keys.clear_all();
unknown's avatar
unknown committed
2142 2143 2144 2145
    table->reginfo.join_tab=s;
    table->reginfo.not_exists_optimize=0;
    bzero((char*) table->const_key_parts, sizeof(key_part_map)*table->keys);
    all_table_map|= table->map;
2146
    s->join=join;
2147
    s->info=0;					// For describe
2148 2149 2150

    s->dependent= tables->dep_tables;
    s->key_dependent= 0;
2151 2152
    if (tables->schema_table)
      table->file->records= 2;
2153

unknown's avatar
unknown committed
2154 2155
    s->on_expr_ref= &tables->on_expr;
    if (*s->on_expr_ref)
unknown's avatar
unknown committed
2156
    {
2157
      /* s is the only inner table of an outer join */
unknown's avatar
unknown committed
2158 2159
      if (!table->file->records)
      {						// Empty table
2160
        s->dependent= 0;                        // Ignore LEFT JOIN depend.
unknown's avatar
unknown committed
2161 2162 2163
	set_position(join,const_count++,s,(KEYUSE*) 0);
	continue;
      }
2164
      outer_join|= table->map;
unknown's avatar
unknown committed
2165 2166
      continue;
    }
2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180
    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;
    }

unknown's avatar
unknown committed
2181
    if ((table->system || table->file->records <= 1) && ! s->dependent &&
2182
	!(table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
unknown's avatar
unknown committed
2183
        !table->fulltext_searched)
unknown's avatar
unknown committed
2184 2185 2186 2187 2188
    {
      set_position(join,const_count++,s,(KEYUSE*) 0);
    }
  }
  stat_vector[i]=0;
2189
  join->outer_join=outer_join;
unknown's avatar
unknown committed
2190

2191
  if (join->outer_join)
unknown's avatar
unknown committed
2192
  {
2193 2194 2195 2196 2197 2198
    /* 
       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
2199
       of the algorithm is O((number of tables)^2). 
2200 2201
    */
    for (i= 0, s= stat ; i < table_count ; i++, s++)
unknown's avatar
unknown committed
2202
    {
2203
      for (uint j= 0 ; j < table_count ; j++)
unknown's avatar
unknown committed
2204
      {
2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215
        table= stat[j].table;
        if (s->dependent & table->map)
          s->dependent |= table->reginfo.join_tab->dependent;
      }
    }
    /* 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
2216
        my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0));
2217
        DBUG_RETURN(1);
unknown's avatar
unknown committed
2218
      }
2219
      s->key_dependent= s->dependent;
unknown's avatar
unknown committed
2220 2221 2222 2223
    }
  }

  if (conds || outer_join)
2224
    if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables,
unknown's avatar
unknown committed
2225 2226
                            conds, join->cond_equal,
                            ~outer_join, join->select_lex))
unknown's avatar
unknown committed
2227 2228
      DBUG_RETURN(1);

2229
  /* Read tables with 0 or 1 rows (system tables) */
2230
  join->const_table_map= 0;
2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248

  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
2249
  /* loop until no more const tables are found */
2250
  int ref_changed;
unknown's avatar
unknown committed
2251 2252
  do
  {
2253
    ref_changed = 0;
unknown's avatar
unknown committed
2254
    found_ref=0;
2255 2256 2257 2258 2259 2260 2261

    /*
      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
2262
    {
2263
      table=s->table;
unknown's avatar
unknown committed
2264 2265
      if (s->dependent)				// If dependent on some table
      {
2266
	// All dep. must be constants
2267
	if (s->dependent & ~(found_const_table_map))
unknown's avatar
unknown committed
2268
	  continue;
2269
	if (table->file->records <= 1L &&
2270 2271
	    !(table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
            !table->pos_in_table_list->embedding)
unknown's avatar
unknown committed
2272
	{					// system table
2273
	  int tmp= 0;
unknown's avatar
unknown committed
2274
	  s->type=JT_SYSTEM;
2275
	  join->const_table_map|=table->map;
unknown's avatar
unknown committed
2276
	  set_position(join,const_count++,s,(KEYUSE*) 0);
2277
	  if ((tmp= join_read_const_table(s,join->positions+const_count-1)))
2278 2279 2280 2281 2282 2283
	  {
	    if (tmp > 0)
	      DBUG_RETURN(1);			// Fatal error
	  }
	  else
	    found_const_table_map|= table->map;
unknown's avatar
unknown committed
2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294
	  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;
2295
	  s->keys.set_bit(key);               // QQ: remove this ?
unknown's avatar
unknown committed
2296

2297 2298 2299
	  refs=0;
          const_ref.clear_all();
	  eq_part.clear_all();
unknown's avatar
unknown committed
2300 2301
	  do
	  {
2302
	    if (keyuse->val->type() != Item::NULL_ITEM && !keyuse->optimize)
unknown's avatar
unknown committed
2303
	    {
2304
	      if (!((~found_const_table_map) & keyuse->used_tables))
2305
		const_ref.set_bit(keyuse->keypart);
unknown's avatar
unknown committed
2306 2307
	      else
		refs|=keyuse->used_tables;
2308
	      eq_part.set_bit(keyuse->keypart);
unknown's avatar
unknown committed
2309 2310 2311 2312
	    }
	    keyuse++;
	  } while (keyuse->table == table && keyuse->key == key);

2313
	  if (eq_part.is_prefix(table->key_info[key].key_parts) &&
2314 2315
	      ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
	       HA_NOSAME) &&
unknown's avatar
unknown committed
2316
              !table->fulltext_searched)
unknown's avatar
unknown committed
2317 2318 2319
	  {
	    if (const_ref == eq_part)
	    {					// Found everything for ref.
2320 2321
	      int tmp;
	      ref_changed = 1;
2322
	      s->type= JT_CONST;
2323
	      join->const_table_map|=table->map;
unknown's avatar
unknown committed
2324
	      set_position(join,const_count++,s,start_keyuse);
2325
	      if (create_ref_for_key(join, s, start_keyuse,
2326
				     found_const_table_map))
2327 2328 2329 2330 2331 2332 2333 2334 2335
		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
2336 2337 2338 2339 2340 2341 2342 2343
	      break;
	    }
	    else
	      found_ref|= refs;		// Table is const if all refs are const
	  }
	}
      }
    }
2344
  } while (join->const_table_map & found_ref && ref_changed);
unknown's avatar
unknown committed
2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357

  /* 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;
2358
    s->read_time=(ha_rows) s->table->file->scan_time();
unknown's avatar
unknown committed
2359

2360 2361
    /*
      Set a max range of how many seeks we can expect when using keys
2362 2363
      This is can't be to high as otherwise we are likely to use
      table scan.
2364
    */
2365 2366
    s->worst_seeks= min((double) s->found_records / 10,
			(double) s->read_time*3);
unknown's avatar
unknown committed
2367 2368 2369
    if (s->worst_seeks < 2.0)			// Fix for small tables
      s->worst_seeks=2.0;

2370 2371 2372 2373 2374 2375
    /*
      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);

2376 2377
    if (!s->const_keys.is_clear_all() &&
        !s->table->pos_in_table_list->embedding)
unknown's avatar
unknown committed
2378 2379
    {
      ha_rows records;
2380 2381 2382
      SQL_SELECT *select;
      select= make_select(s->table, found_const_table_map,
			  found_const_table_map,
unknown's avatar
unknown committed
2383
			  *s->on_expr_ref ? *s->on_expr_ref : conds,
2384 2385 2386
			  &error, true);
      if (!select)
        DBUG_RETURN(1);
2387
      records= get_quick_record_count(join->thd, select, s->table,
unknown's avatar
unknown committed
2388
				      &s->const_keys, join->row_limit);
unknown's avatar
unknown committed
2389 2390 2391
      s->quick=select->quick;
      s->needed_reg=select->needed_reg;
      select->quick=0;
2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402
      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
2403
	if (*s->on_expr_ref)
2404 2405 2406 2407 2408 2409 2410 2411
	{
	  /* 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
2412 2413
      if (records != HA_POS_ERROR)
      {
2414
	s->found_records=records;
unknown's avatar
unknown committed
2415 2416
	s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
      }
2417
      delete select;
unknown's avatar
unknown committed
2418 2419 2420 2421 2422 2423 2424
    }
  }

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

2427
  /* Find an optimal join order of the non-constant tables. */
unknown's avatar
unknown committed
2428
  if (join->const_tables != join->tables)
2429 2430
  {
    optimize_keyuse(join, keyuse_array);
unknown's avatar
af  
unknown committed
2431
    choose_plan(join, all_table_map & ~join->const_table_map);
2432
  }
unknown's avatar
unknown committed
2433 2434 2435 2436 2437 2438
  else
  {
    memcpy((gptr) join->best_positions,(gptr) join->positions,
	   sizeof(POSITION)*join->const_tables);
    join->best_read=1.0;
  }
2439
  /* Generate an execution plan from the found optimal join order. */
unknown's avatar
unknown committed
2440
  DBUG_RETURN(join->thd->killed || get_best_combination(join));
unknown's avatar
unknown committed
2441 2442 2443 2444
}


/*****************************************************************************
2445 2446 2447 2448 2449
  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
2450 2451 2452 2453 2454
*****************************************************************************/

typedef struct key_field_t {		// Used when finding key fields
  Field		*field;
  Item		*val;			// May be empty if diff constant
2455 2456
  uint		level;
  uint		optimize;
unknown's avatar
unknown committed
2457 2458 2459
  bool		eq_func;
} KEY_FIELD;

2460 2461 2462 2463 2464 2465 2466 2467
/* 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
2468

2469 2470 2471 2472 2473 2474
  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 
*/
unknown's avatar
unknown committed
2475 2476 2477 2478 2479 2480 2481 2482

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
2483
    return start;				// No new fields, skip all
unknown's avatar
unknown committed
2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495

  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())
	{
2496 2497 2498 2499
	  /*
	    If the value matches, we can use the key reference.
	    If not, we keep it until we have examined all new values
	  */
2500
	  if (old->val->eq(new_fields->val, old->field->binary()))
unknown's avatar
unknown committed
2501
	  {
2502 2503 2504 2505 2506
	    old->level= and_level;
	    old->optimize= ((old->optimize & new_fields->optimize &
			     KEY_OPTIMIZE_EXISTS) |
			    ((old->optimize | new_fields->optimize) &
			     KEY_OPTIMIZE_REF_OR_NULL));
unknown's avatar
unknown committed
2507 2508
	  }
	}
2509 2510
	else if (old->eq_func && new_fields->eq_func &&
		 old->val->eq(new_fields->val, old->field->binary()))
2511

2512 2513 2514 2515 2516 2517 2518 2519 2520
	{
	  old->level= and_level;
	  old->optimize= ((old->optimize & new_fields->optimize &
			   KEY_OPTIMIZE_EXISTS) |
			  ((old->optimize | new_fields->optimize) &
			   KEY_OPTIMIZE_REF_OR_NULL));
	}
	else if (old->eq_func && new_fields->eq_func &&
		 (old->val->is_null() || new_fields->val->is_null()))
unknown's avatar
unknown committed
2521
	{
2522 2523 2524 2525 2526 2527
	  /* 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;
unknown's avatar
unknown committed
2528
	}
2529
	else
unknown's avatar
unknown committed
2530
	{
2531 2532 2533 2534 2535
	  /*
	    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
2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546
	  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 ;)
  {
2547
    if (old->level != and_level)
unknown's avatar
unknown committed
2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559
    {						// Not used in all levels
      if (old == --first_free)
	break;
      *old= *first_free;			// Remove old value
      continue;
    }
    old++;
  }
  return first_free;
}


2560 2561 2562 2563 2564 2565 2566
/*
  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
2567
    cond                        Condition predicate
2568 2569 2570
    field			Field used in comparision
    eq_func			True if we used =, <=> or IS NULL
    value			Value used for comparison with field
2571
                                Is NULL for BETWEEN and IN
2572 2573 2574 2575 2576 2577 2578 2579 2580 2581
    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
2582
static void
2583 2584
add_key_field(KEY_FIELD **key_fields, uint and_level, COND *cond,
	      Field *field, bool eq_func, Item **value, uint num_values,
unknown's avatar
unknown committed
2585 2586
	      table_map usable_tables)
{
2587
  uint exists_optimize= 0;
unknown's avatar
unknown committed
2588 2589 2590
  if (!(field->flags & PART_KEY_FLAG))
  {
    // Don't remove column IS NULL on a LEFT JOIN table
2591 2592
    if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
        !field->table->maybe_null || field->null_ptr)
unknown's avatar
unknown committed
2593
      return;					// Not a key. Skip it
2594
    exists_optimize= KEY_OPTIMIZE_EXISTS;
unknown's avatar
unknown committed
2595 2596 2597 2598
  }
  else
  {
    table_map used_tables=0;
2599 2600 2601
    bool optimizable=0;
    for (uint i=0; i<num_values; i++)
    {
unknown's avatar
af  
unknown committed
2602 2603
      used_tables|=(value[i])->used_tables();
      if (!((value[i])->used_tables() & (field->table->map | RAND_TABLE_BIT)))
2604 2605 2606
        optimizable=1;
    }
    if (!optimizable)
unknown's avatar
unknown committed
2607 2608 2609
      return;
    if (!(usable_tables & field->table->map))
    {
2610 2611
      if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
          !field->table->maybe_null || field->null_ptr)
unknown's avatar
unknown committed
2612
	return;					// Can't use left join optimize
2613
      exists_optimize= KEY_OPTIMIZE_EXISTS;
unknown's avatar
unknown committed
2614 2615 2616 2617
    }
    else
    {
      JOIN_TAB *stat=field->table->reginfo.join_tab;
unknown's avatar
unknown committed
2618
      key_map possible_keys=field->key_start;
2619 2620
      possible_keys.intersect(field->table->keys_in_use_for_query);
      stat[0].keys.merge(possible_keys);             // Add possible keys
unknown's avatar
unknown committed
2621

2622 2623 2624 2625 2626 2627 2628 2629
      /*
	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
2630 2631
         Field BETWEEN ...
         Field IN ...
unknown's avatar
unknown committed
2632 2633 2634
      */
      stat[0].key_dependent|=used_tables;

2635 2636
      bool is_const=1;
      for (uint i=0; i<num_values; i++)
2637
        is_const&= value[i]->const_item();
2638
      if (is_const)
2639
        stat[0].const_keys.merge(possible_keys);
2640 2641
      /*
	We can't always use indexes when comparing a string index to a
unknown's avatar
unknown committed
2642 2643
	number. cmp_type() is checked to allow compare of dates to numbers.
        eq_func is NEVER true when num_values > 1
2644
       */
2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658
      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
2659

2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670
            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
2671 2672
    }
  }
2673
  DBUG_ASSERT(num_values == 1);
unknown's avatar
unknown committed
2674 2675 2676 2677 2678
  /*
    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
2679
  /* Store possible eq field */
2680 2681
  (*key_fields)->field=		field;
  (*key_fields)->eq_func=	eq_func;
unknown's avatar
unknown committed
2682
  (*key_fields)->val=		*value;
2683 2684
  (*key_fields)->level=		and_level;
  (*key_fields)->optimize=	exists_optimize;
unknown's avatar
unknown committed
2685 2686 2687 2688
  (*key_fields)++;
}


unknown's avatar
unknown committed
2689 2690 2691 2692
/*
  Add possible keys to array of possible keys originated from a simple predicate

  SYNPOSIS
2693
    add_key_equal_fields()
unknown's avatar
unknown committed
2694 2695
    key_fields			Pointer to add key, if usable
    and_level			And level, to be stored in KEY_FIELD
2696
    cond                        Condition predicate
unknown's avatar
unknown committed
2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710
    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
*/

2711 2712
static void
add_key_equal_fields(KEY_FIELD **key_fields, uint and_level,
2713
                     COND *cond, Item_field *field_item,
2714 2715 2716 2717
                     bool eq_func, Item **val,
                     uint num_values, table_map usable_tables)
{
  Field *field= field_item->field;
2718
  add_key_field(key_fields, and_level, cond, field,
2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732
                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))
      {
2733
        add_key_field(key_fields, and_level, cond, item->field,
2734 2735 2736 2737 2738 2739
                      eq_func, val, num_values, usable_tables);
      }
    }
  }
}

unknown's avatar
unknown committed
2740 2741 2742 2743 2744 2745
static void
add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
	       COND *cond, table_map usable_tables)
{
  if (cond->type() == Item_func::COND_ITEM)
  {
unknown's avatar
unknown committed
2746
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
2747 2748 2749 2750 2751 2752 2753 2754
    KEY_FIELD *org_key_fields= *key_fields;

    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
    {
      Item *item;
      while ((item=li++))
	add_key_fields(stat,key_fields,and_level,item,usable_tables);
      for (; org_key_fields != *key_fields ; org_key_fields++)
2755
	org_key_fields->level= *and_level;
unknown's avatar
unknown committed
2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781
    }
    else
    {
      (*and_level)++;
      add_key_fields(stat,key_fields,and_level,li++,usable_tables);
      Item *item;
      while ((item=li++))
      {
	KEY_FIELD *start_key_fields= *key_fields;
	(*and_level)++;
	add_key_fields(stat,key_fields,and_level,item,usable_tables);
	*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
2782 2783
  {
    // BETWEEN, IN, NE
2784
    if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
unknown's avatar
unknown committed
2785
	!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799
    {
      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
2800
    break;
unknown's avatar
unknown committed
2801
  }
unknown's avatar
unknown committed
2802 2803 2804 2805 2806
  case Item_func::OPTIMIZE_OP:
  {
    bool equal_func=(cond_func->functype() == Item_func::EQ_FUNC ||
		     cond_func->functype() == Item_func::EQUAL_FUNC);

2807
    if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
unknown's avatar
unknown committed
2808
	!(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
2809
    {
2810
      add_key_equal_fields(key_fields, *and_level, cond_func,
2811 2812 2813
	                (Item_field*) (cond_func->arguments()[0])->real_item(),
		           equal_func,
		           cond_func->arguments()+1, 1, usable_tables);
unknown's avatar
unknown committed
2814
    }
unknown's avatar
unknown committed
2815
    if (cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
2816
	cond_func->functype() != Item_func::LIKE_FUNC &&
unknown's avatar
unknown committed
2817
	!(cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
2818
    {
2819
      add_key_equal_fields(key_fields, *and_level, cond_func, 
2820 2821 2822
                       (Item_field*) (cond_func->arguments()[1])->real_item(),
		           equal_func,
		           cond_func->arguments(),1,usable_tables);
unknown's avatar
unknown committed
2823 2824 2825 2826 2827
    }
    break;
  }
  case Item_func::OPTIMIZE_NULL:
    /* column_name IS [NOT] NULL */
2828
    if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
unknown's avatar
unknown committed
2829
	!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
2830
    {
2831
      Item *tmp=new Item_null;
2832
      if (unlikely(!tmp))                       // Should never be true
unknown's avatar
unknown committed
2833
	return;
2834
      add_key_equal_fields(key_fields, *and_level, cond_func,
2835
		    (Item_field*) (cond_func->arguments()[0])->real_item(),
unknown's avatar
unknown committed
2836
		    cond_func->functype() == Item_func::ISNULL_FUNC,
2837
		    &tmp, 1, usable_tables);
unknown's avatar
unknown committed
2838 2839
    }
    break;
2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853
  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++))
      {
2854
        add_key_field(key_fields, *and_level, cond, item->field,
2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873
                      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))
          {
2874
            add_key_field(key_fields, *and_level, cond, field,
2875 2876 2877 2878 2879 2880 2881
                          TRUE, (Item **) &item, 1, usable_tables);
          }
        }
        it.rewind();
      }
    }
    break;
unknown's avatar
unknown committed
2882 2883 2884 2885
  }
}

/*
2886 2887
  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
2888 2889 2890
*/

static uint
2891
max_part_bit(key_part_map bits)
unknown's avatar
unknown committed
2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904
{
  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;

2905
  if (key_field->eq_func && !(key_field->optimize & KEY_OPTIMIZE_EXISTS))
unknown's avatar
unknown committed
2906 2907 2908
  {
    for (uint key=0 ; key < form->keys ; key++)
    {
2909
      if (!(form->keys_in_use_for_query.is_set(key)))
unknown's avatar
unknown committed
2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922
	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;
2923
	  keyuse.keypart_map= (key_part_map) 1 << part;
unknown's avatar
unknown committed
2924
	  keyuse.used_tables=key_field->val->used_tables();
2925
	  keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL;
unknown's avatar
unknown committed
2926 2927 2928 2929 2930 2931 2932
	  VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
	}
      }
    }
  }
}

unknown's avatar
unknown committed
2933 2934 2935

#define FT_KEYPART   (MAX_REF_PARTS+10)

unknown's avatar
unknown committed
2936 2937 2938 2939
static void
add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
            JOIN_TAB *stat,COND *cond,table_map usable_tables)
{
2940
  Item_func_match *cond_func=NULL;
unknown's avatar
unknown committed
2941

2942 2943 2944
  if (!cond)
    return;

2945 2946
  if (cond->type() == Item::FUNC_ITEM)
  {
2947 2948 2949
    Item_func *func=(Item_func *)cond;
    Item_func::Functype functype=  func->functype();
    if (functype == Item_func::FT_FUNC)
2950
      cond_func=(Item_func_match *)cond;
2951 2952 2953 2954
    else if (func->arg_count == 2)
    {
      Item_func *arg0=(Item_func *)(func->arguments()[0]),
                *arg1=(Item_func *)(func->arguments()[1]);
2955
      if (arg1->const_item()  &&
2956 2957
          ((functype == Item_func::GE_FUNC && arg1->val_real() > 0) ||
           (functype == Item_func::GT_FUNC && arg1->val_real() >=0))  &&
2958 2959
           arg0->type() == Item::FUNC_ITEM            &&
           arg0->functype() == Item_func::FT_FUNC)
2960
        cond_func=(Item_func_match *) arg0;
2961
      else if (arg0->const_item() &&
2962 2963
               ((functype == Item_func::LE_FUNC && arg0->val_real() > 0) ||
                (functype == Item_func::LT_FUNC && arg0->val_real() >=0)) &&
2964
                arg1->type() == Item::FUNC_ITEM          &&
2965
                arg1->functype() == Item_func::FT_FUNC)
2966 2967
        cond_func=(Item_func_match *) arg1;
    }
2968 2969 2970
  }
  else if (cond->type() == Item::COND_ITEM)
  {
unknown's avatar
unknown committed
2971
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
2972 2973 2974 2975 2976

    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
    {
      Item *item;
      while ((item=li++))
2977
        add_ft_keys(keyuse_array,stat,item,usable_tables);
2978 2979 2980
    }
  }

2981 2982
  if (!cond_func || cond_func->key == NO_SUCH_KEY ||
      !(usable_tables & cond_func->table->map))
2983
    return;
unknown's avatar
unknown committed
2984 2985 2986

  KEYUSE keyuse;
  keyuse.table= cond_func->table;
2987
  keyuse.val =  cond_func;
unknown's avatar
unknown committed
2988
  keyuse.key =  cond_func->key;
unknown's avatar
unknown committed
2989
  keyuse.keypart= FT_KEYPART;
2990
  keyuse.used_tables=cond_func->key_item()->used_tables();
unknown's avatar
unknown committed
2991
  keyuse.optimize= 0;
unknown's avatar
unknown committed
2992
  keyuse.keypart_map= 0;
unknown's avatar
unknown committed
2993 2994 2995
  VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
}

2996

unknown's avatar
unknown committed
2997 2998 2999
static int
sort_keyuse(KEYUSE *a,KEYUSE *b)
{
3000
  int res;
unknown's avatar
unknown committed
3001 3002 3003 3004 3005 3006
  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);
3007
  // Place const values before other ones
3008 3009
  if ((res= test((a->used_tables & ~OUTER_REF_TABLE_BIT)) -
       test((b->used_tables & ~OUTER_REF_TABLE_BIT))))
3010 3011 3012 3013
    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
3014 3015 3016 3017
}


/*
3018 3019 3020
  Update keyuse array with all possible keys we can use to fetch rows
  join_tab is a array in tablenr_order
  stat is a reference array in 'prefered' order.
unknown's avatar
unknown committed
3021 3022 3023
*/

static bool
3024
update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
unknown's avatar
unknown committed
3025 3026
		    uint tables, COND *cond, COND_EQUAL *cond_equal,
                    table_map normal_tables, SELECT_LEX *select_lex)
unknown's avatar
unknown committed
3027 3028
{
  uint	and_level,i,found_eq_constant;
unknown's avatar
unknown committed
3029
  KEY_FIELD *key_fields, *end, *field;
unknown's avatar
unknown committed
3030 3031 3032 3033
  uint m= 1;
  
  if (cond_equal && cond_equal->max_members)
    m= cond_equal->max_members;
unknown's avatar
unknown committed
3034

3035
  if (!(key_fields=(KEY_FIELD*)
unknown's avatar
merge  
unknown committed
3036
	thd->alloc(sizeof(key_fields[0])*
unknown's avatar
unknown committed
3037
		   (thd->lex->current_select->cond_count+1)*2*m)))
3038
    return TRUE; /* purecov: inspected */
unknown's avatar
unknown committed
3039 3040 3041 3042
  and_level= 0;
  field= end= key_fields;
  if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
    return TRUE;
3043
  if (cond)
unknown's avatar
unknown committed
3044
  {
3045
    add_key_fields(join_tab,&end,&and_level,cond,normal_tables);
unknown's avatar
unknown committed
3046
    for (; field != end ; field++)
unknown's avatar
unknown committed
3047
    {
unknown's avatar
unknown committed
3048 3049 3050 3051 3052
      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
3053
    }
unknown's avatar
unknown committed
3054
  }
3055
  for (i=0 ; i < tables ; i++)
unknown's avatar
unknown committed
3056
  {
3057 3058 3059 3060 3061 3062 3063 3064 3065
    /*
      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
3066
    if (*join_tab[i].on_expr_ref)
unknown's avatar
unknown committed
3067
    {
unknown's avatar
unknown committed
3068
      add_key_fields(join_tab,&end,&and_level,*join_tab[i].on_expr_ref,
3069
		     join_tab[i].table->map);
unknown's avatar
unknown committed
3070
    }
3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082
    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)
          add_key_fields(join_tab, &end, &and_level, embedding->on_expr,
                         nested_join->used_tables);
      }
    }
unknown's avatar
unknown committed
3083
  }
3084
  /* fill keyuse with found key parts */
unknown's avatar
unknown committed
3085
  for ( ; field != end ; field++)
3086
    add_key_part(keyuse,field);
unknown's avatar
unknown committed
3087

3088
  if (select_lex->ftfunc_list->elements)
unknown's avatar
unknown committed
3089 3090 3091 3092 3093
  {
    add_ft_keys(keyuse,join_tab,cond,normal_tables);
  }

  /*
3094
    Special treatment for ft-keys.
3095 3096 3097
    Remove the following things from KEYUSE:
    - ref if there is a keypart which is a ref and a const.
    - keyparts without previous keyparts.
unknown's avatar
unknown committed
3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114
  */
  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)
3115
	use->table->const_key_parts[use->key]|= use->keypart_map;
unknown's avatar
unknown committed
3116 3117
      if (use->keypart != FT_KEYPART)
      {
3118 3119 3120 3121 3122 3123 3124 3125
	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
3126 3127 3128 3129 3130 3131 3132 3133
      }

      *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;
3134
      use->table->reginfo.join_tab->checked_keys.set_bit(use->key);
unknown's avatar
unknown committed
3135 3136 3137 3138 3139 3140 3141 3142 3143
      save_pos++;
    }
    i=(uint) (save_pos-(KEYUSE*) keyuse->buffer);
    VOID(set_dynamic(keyuse,(gptr) &end,i));
    keyuse->elements=i;
  }
  return FALSE;
}

3144
/*
unknown's avatar
af  
unknown committed
3145
  Update some values in keyuse for faster choose_plan() loop
3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162
*/

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
3163
    keyuse->ref_table_rows= ~(ha_rows) 0;	// If no ref
3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175
    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
3176 3177 3178 3179 3180 3181 3182 3183 3184 3185
    /*
      Outer reference (external field) is constant for single executing
      of subquery
    */
    if (keyuse->used_tables == OUTER_REF_TABLE_BIT)
      keyuse->ref_table_rows= 1;
  }
}


3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247
/*
  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
3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 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 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
/*****************************************************************************
  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 +
                    ((double) (table->max_key_length-keyinfo->key_length) /
                     (double) table->max_key_length)));
                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
3447
              (!(table->file->index_flags(key, 0, 0) & HA_ONLY_WHOLE_INDEX) ||
unknown's avatar
af  
unknown committed
3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466
               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
3467
                  and that the whole key matches 10 (duplicates) or 1
unknown's avatar
af  
unknown committed
3468 3469 3470 3471 3472 3473 3474
                  (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
3475
                  a = records matched by first key part (1% of all records?)
unknown's avatar
af  
unknown committed
3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490
                  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
3491 3492 3493 3494 3495 3496
                  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
3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589
                  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
3590
      if (s->table->map & join->outer_join)     // Can't use join cache
unknown's avatar
af  
unknown committed
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 3664 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
      {
        /*
          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;

  DBUG_ENTER("choose_plan");

  if (join->select_options & SELECT_STRAIGHT_JOIN)
  {
    optimize_straight_join(join, join_tables);
  }
  else
  {
    /*
      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*), join_tab_cmp);

    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);
    }
  }

  /* Store the cost of this query into a user variable */
  last_query_cost= join->best_read;

  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
3737 3738 3739 3740 3741

  if (jt1->dependent & jt2->table->map)
    return 1;
  if (jt2->dependent & jt1->table->map)
    return -1;  
unknown's avatar
af  
unknown committed
3742 3743
  if (jt1->found_records > jt2->found_records)
    return 1;
unknown's avatar
unknown committed
3744 3745 3746
  if (jt1->found_records < jt2->found_records)
    return -1; 
  return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
unknown's avatar
af  
unknown committed
3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 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 3931 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
}


/*
  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;

  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
4094

unknown's avatar
af  
unknown committed
4095 4096 4097 4098 4099 4100 4101 4102
  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
4103

unknown's avatar
af  
unknown committed
4104 4105 4106
  RETURN
    None
*/
unknown's avatar
unknown committed
4107 4108

static void
unknown's avatar
af  
unknown committed
4109 4110 4111 4112 4113 4114 4115
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
4116
{
unknown's avatar
af  
unknown committed
4117 4118 4119
  THD *thd= join->thd;
  if (thd->killed)  // Abort
    return;
unknown's avatar
unknown committed
4120

unknown's avatar
af  
unknown committed
4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134
  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
4135
  {
unknown's avatar
af  
unknown committed
4136 4137 4138 4139
    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
4140

unknown's avatar
af  
unknown committed
4141 4142 4143 4144 4145
      /* 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
4146

unknown's avatar
af  
unknown committed
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 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212
      /* 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
4213
          join->best_read= current_read_time - 0.001;
unknown's avatar
af  
unknown committed
4214 4215 4216 4217 4218 4219
        }
        DBUG_EXECUTE("opt",
                     print_plan(join, current_read_time, current_record_count, idx, "full_plan"););
      }
    }
  }
unknown's avatar
unknown committed
4220 4221 4222 4223
  DBUG_VOID_RETURN;
}


unknown's avatar
af  
unknown committed
4224 4225 4226 4227
/*
  TODO: this function is here only temporarily until 'greedy_search' is
  tested and accepted.
*/
unknown's avatar
unknown committed
4228 4229 4230 4231
static void
find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
	  double read_time)
{
4232
  ha_rows rec;
unknown's avatar
unknown committed
4233
  double tmp;
unknown's avatar
unknown committed
4234
  THD *thd= join->thd;
unknown's avatar
unknown committed
4235 4236 4237 4238 4239 4240 4241 4242

  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
4243 4244
	join->sort_by_table !=
	join->positions[join->const_tables].table->table)
unknown's avatar
unknown committed
4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266
      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);
      join->best_read=read_time;
    }
    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;
4267
      uint best_max_key_part=0;
4268
      my_bool found_constraint= 0;
unknown's avatar
unknown committed
4269 4270 4271 4272 4273 4274

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

	/* Test how we can use keys */
4278
	rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE;  // Assumed records/key
unknown's avatar
unknown committed
4279 4280
	for (keyuse=s->keyuse ; keyuse->table == table ;)
	{
4281
	  key_part_map found_part=0;
unknown's avatar
unknown committed
4282 4283 4284 4285
	  table_map found_ref=0;
	  uint key=keyuse->key;
	  KEY *keyinfo=table->key_info+key;
          bool ft_key=(keyuse->keypart == FT_KEYPART);
4286
	  uint found_ref_or_null= 0;
unknown's avatar
unknown committed
4287

4288
	  /* Calculate how many key segments of the current key we can use */
unknown's avatar
unknown committed
4289 4290 4291 4292
	  start_key=keyuse;
	  do
	  {
            uint keypart=keyuse->keypart;
unknown's avatar
af  
unknown committed
4293 4294
            table_map best_part_found_ref= 0;
            double best_prev_record_reads= DBL_MAX;
unknown's avatar
unknown committed
4295 4296
	    do
	    {
4297 4298 4299 4300
	      if (!(rest_tables & keyuse->used_tables) &&
		  !(found_ref_or_null & keyuse->optimize))
	      {
		found_part|=keyuse->keypart_map;
unknown's avatar
af  
unknown committed
4301 4302 4303 4304 4305 4306 4307 4308
                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;
                }
4309 4310
		if (rec > keyuse->ref_table_rows)
		  rec= keyuse->ref_table_rows;
unknown's avatar
af  
unknown committed
4311 4312
		/*
		  If there is one 'key_column IS NULL' expression, we can
4313
		  use this ref_or_null optimisation of this field
unknown's avatar
af  
unknown committed
4314 4315 4316
		*/
		found_ref_or_null|= (keyuse->optimize &
				     KEY_OPTIMIZE_REF_OR_NULL);
unknown's avatar
unknown committed
4317 4318 4319 4320
              }
	      keyuse++;
	    } while (keyuse->table == table && keyuse->key == key &&
		     keyuse->keypart == keypart);
unknown's avatar
af  
unknown committed
4321
	    found_ref|= best_part_found_ref;
unknown's avatar
unknown committed
4322 4323 4324
	  } while (keyuse->table == table && keyuse->key == key);

	  /*
4325
	    Assume that that each key matches a proportional part of table.
unknown's avatar
unknown committed
4326 4327 4328
	  */
          if (!found_part && !ft_key)
	    continue;				// Nothing usable found
4329 4330
	  if (rec < MATCHING_ROWS_IN_OTHER_TABLE)
	    rec= MATCHING_ROWS_IN_OTHER_TABLE;	// Fix for small tables
unknown's avatar
unknown committed
4331 4332

          /*
4333
	    ft-keys require special treatment
unknown's avatar
unknown committed
4334 4335 4336 4337
          */
          if (ft_key)
          {
            /*
4338 4339
	      Really, there should be records=0.0 (yes!)
	      but 1.0 would be probably safer
unknown's avatar
unknown committed
4340 4341 4342 4343 4344 4345
            */
            tmp=prev_record_reads(join,found_ref);
            records=1.0;
          }
          else
          {
4346
	  found_constraint= 1;
unknown's avatar
unknown committed
4347
	  /*
4348
	    Check if we found full key
unknown's avatar
unknown committed
4349
	  */
4350 4351
	  if (found_part == PREV_BITS(uint,keyinfo->key_parts) &&
	      !found_ref_or_null)
unknown's avatar
unknown committed
4352
	  {				/* use eq key */
4353
	    max_key_part= (uint) ~0;
4354 4355
	    if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
				   HA_END_SPACE_KEY)) == HA_NOSAME)
unknown's avatar
unknown committed
4356 4357 4358 4359 4360 4361
	    {
	      tmp=prev_record_reads(join,found_ref);
	      records=1.0;
	    }
	    else
	    {
4362 4363
	      if (!found_ref)
	      {					// We found a const key
4364
		if (table->quick_keys.is_set(key))
unknown's avatar
unknown committed
4365 4366
		  records= (double) table->quick_rows[key];
		else
unknown's avatar
unknown committed
4367 4368 4369 4370
		{
		  /* quick_range couldn't use key! */
		  records= (double) s->records/rec;
		}
unknown's avatar
unknown committed
4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384
	      }
	      else
	      {
		if (!(records=keyinfo->rec_per_key[keyinfo->key_parts-1]))
		{				// Prefere longer keys
		  records=
		    ((double) s->records / (double) rec *
		     (1.0 +
		      ((double) (table->max_key_length-keyinfo->key_length) /
		       (double) table->max_key_length)));
		  if (records < 2.0)
		    records=2.0;		// Can't be as good as a unique
		}
	      }
4385 4386 4387
	      /* Limit the number of matched rows */
	      tmp= records;
	      set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
4388
	      if (table->used_keys.is_set(key))
unknown's avatar
unknown committed
4389 4390 4391
	      {
		/* we can use only index tree */
		uint keys_per_block= table->file->block_size/2/
unknown's avatar
unknown committed
4392
		  (keyinfo->key_length+table->file->ref_length)+1;
4393
		tmp=record_count*(tmp+keys_per_block-1)/keys_per_block;
unknown's avatar
unknown committed
4394 4395
	      }
	      else
4396
		tmp=record_count*min(tmp,s->worst_seeks);
unknown's avatar
unknown committed
4397 4398 4399 4400 4401
	    }
	  }
	  else
	  {
	    /*
4402 4403 4404
	      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
4405
	    */
4406
	    if ((found_part & 1) &&
4407
		(!(table->file->index_flags(key,0,0) & HA_ONLY_WHOLE_INDEX) ||
4408
		 found_part == PREV_BITS(uint,keyinfo->key_parts)))
unknown's avatar
unknown committed
4409
	    {
4410
	      max_key_part=max_part_bit(found_part);
4411 4412 4413 4414
	      /*
		Check if quick_range could determinate how many rows we
		will match
	      */
4415
	      if (table->quick_keys.is_set(key) &&
unknown's avatar
af  
unknown committed
4416
		  table->quick_key_parts[key] == max_key_part)
unknown's avatar
unknown committed
4417 4418 4419 4420 4421 4422 4423 4424 4425
		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
		{
		  /*
4426
		    Assume that the first key part matches 1% of the file
unknown's avatar
unknown committed
4427
		    and that the whole key matches 10 (duplicates) or 1
4428 4429 4430 4431 4432
		    (unique) records.
		    Assume also that more key matches proportionally more
		    records
		    This gives the formula:
		    records= (x * (b-a) + a*c-b)/(c-1)
4433

4434 4435 4436 4437
		    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
4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457
		  */
		  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;
		    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
4458 4459 4460 4461 4462 4463 4464 4465 4466
		/*
		  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)
4467 4468 4469 4470 4471
		{
		  /* We need to do two key searches to find key */
		  tmp*= 2.0;
		  records*= 2.0;
		}
unknown's avatar
unknown committed
4472
	      }
4473 4474
	      /* Limit the number of matched rows */
	      set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
4475
	      if (table->used_keys.is_set(key))
unknown's avatar
unknown committed
4476 4477 4478
	      {
		/* we can use only index tree */
		uint keys_per_block= table->file->block_size/2/
unknown's avatar
unknown committed
4479
		  (keyinfo->key_length+table->file->ref_length)+1;
unknown's avatar
unknown committed
4480 4481 4482 4483 4484 4485 4486 4487
		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
	  }
4488
          } /* not ft_key */
unknown's avatar
unknown committed
4489 4490 4491 4492 4493 4494
	  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;
4495
	    best_max_key_part=max_key_part;
unknown's avatar
unknown committed
4496 4497 4498 4499
	  }
	}
	records=best_records;
      }
4500 4501 4502 4503

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

	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.
4509 4510 4511
      */
      if ((records >= s->found_records || best > s->read_time) &&
	  !(s->quick && best_key && s->quick->index == best_key->key &&
4512
	    best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
4513
	  !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
4514
	    ! s->table->used_keys.is_clear_all() && best_key) &&
4515
	  !(s->table->force_index && best_key))
unknown's avatar
unknown committed
4516
      {						// Check full join
4517 4518 4519 4520 4521 4522 4523 4524 4525 4526
        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;

4527 4528 4529 4530 4531 4532
        /*
          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)
4533
        {
4534 4535 4536 4537 4538
          /*
            For each record we:
             - read record range through 'quick'
             - skip rows which does not satisfy WHERE constraints
           */
4539
          tmp= record_count *
4540 4541
               (s->quick->read_time +
               (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE);
4542 4543 4544
        }
        else
        {
4545 4546
          /* Estimate cost of reading table. */
          tmp= s->table->file->scan_time();
4547
          if (s->table->map  & join->outer_join)      // Can't use join cache
4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572
          {
            /*
              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;
          }
4573
        }
4574

4575
        /*
4576
          We estimate the cost of evaluating WHERE clause for found records
4577
          as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus
4578
          tmp give us total cost of using TABLE SCAN
unknown's avatar
unknown committed
4579
        */
unknown's avatar
unknown committed
4580
	if (best == DBL_MAX ||
4581
	    (tmp  + record_count/(double) TIME_FOR_COMPARE*rnd_records <
unknown's avatar
unknown committed
4582 4583
	     best + record_count/(double) TIME_FOR_COMPARE*records))
	{
4584 4585 4586 4587
	  /*
	    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
4588
	  best=tmp;
4589
	  records= rows2double(rnd_records);
unknown's avatar
unknown committed
4590 4591 4592
	  best_key=0;
	}
      }
4593
      join->positions[idx].records_read= records;
unknown's avatar
unknown committed
4594 4595 4596
      join->positions[idx].key=best_key;
      join->positions[idx].table= s;
      if (!best_key && idx == join->const_tables &&
unknown's avatar
unknown committed
4597
	  s->table == join->sort_by_table &&
4598
	  join->unit->select_limit_cnt >= records)
unknown's avatar
unknown committed
4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617
	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
4618
	swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
unknown's avatar
unknown committed
4619 4620
	find_best(join,rest_tables & ~real_table_bit,idx+1,
		  current_record_count,current_read_time);
unknown's avatar
unknown committed
4621 4622
        if (thd->killed)
          return;
unknown's avatar
af  
unknown committed
4623
	swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
unknown's avatar
unknown committed
4624 4625 4626 4627 4628 4629 4630 4631 4632
      }
      if (join->select_options & SELECT_STRAIGHT_JOIN)
	break;				// Don't test all combinations
    }
  }
}


/*
4633
  Find how much space the prevous read not const tables takes in cache
unknown's avatar
unknown committed
4634 4635
*/

4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 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
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)
    rec_length+=(join_tab->table->null_fields+7)/8;
  if (join_tab->table->maybe_null)
    rec_length+=sizeof(my_bool);
  if (blobs)
  {
    uint blob_length=(uint) (join_tab->table->file->mean_rec_length-
			     (join_tab->table->reclength- rec_length));
    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
4671 4672 4673
static uint
cache_record_length(JOIN *join,uint idx)
{
4674
  uint length=0;
unknown's avatar
unknown committed
4675
  JOIN_TAB **pos,**end;
4676
  THD *thd=join->thd;
unknown's avatar
unknown committed
4677 4678 4679 4680 4681 4682

  for (pos=join->best_ref+join->const_tables,end=join->best_ref+idx ;
       pos != end ;
       pos++)
  {
    JOIN_TAB *join_tab= *pos;
4683 4684
    if (!join_tab->used_fieldlength)		/* Not calced yet */
      calc_used_field_length(thd, join_tab);
unknown's avatar
unknown committed
4685 4686 4687 4688 4689 4690 4691 4692 4693 4694
    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
4695
  found_ref&= ~OUTER_REF_TABLE_BIT;
unknown's avatar
unknown committed
4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708
  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;
}


/*****************************************************************************
4709
  Set up join struct according to best position.
unknown's avatar
unknown committed
4710 4711 4712 4713 4714
*****************************************************************************/

static bool
get_best_combination(JOIN *join)
{
4715
  uint i,tablenr;
unknown's avatar
unknown committed
4716 4717 4718 4719
  table_map used_tables;
  JOIN_TAB *join_tab,*j;
  KEYUSE *keyuse;
  uint table_count;
4720
  THD *thd=join->thd;
unknown's avatar
unknown committed
4721 4722 4723

  table_count=join->tables;
  if (!(join->join_tab=join_tab=
4724
	(JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*table_count)))
unknown's avatar
unknown committed
4725 4726 4727 4728
    return TRUE;

  join->full_join=0;

unknown's avatar
unknown committed
4729
  used_tables= OUTER_REF_TABLE_BIT;		// Outer row is already read
unknown's avatar
unknown committed
4730 4731 4732 4733 4734 4735 4736
  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
4737
    if (!*j->on_expr_ref)
unknown's avatar
unknown committed
4738
      form->reginfo.not_exists_optimize=0;	// Only with LEFT JOIN
4739 4740 4741 4742 4743
    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
4744 4745 4746

    if (j->type == JT_SYSTEM)
      continue;
4747
    if (j->keys.is_clear_all() || !(keyuse= join->best_positions[tablenr].key))
unknown's avatar
unknown committed
4748 4749 4750 4751 4752
    {
      j->type=JT_ALL;
      if (tablenr != join->const_tables)
	join->full_join=1;
    }
4753 4754 4755
    else if (create_ref_for_key(join, j, keyuse, used_tables))
      return TRUE;				// Something went wrong
  }
unknown's avatar
unknown committed
4756

4757 4758 4759 4760 4761
  for (i=0 ; i < table_count ; i++)
    join->map2table[join->join_tab[i].table->tablenr]=join->join_tab+i;
  update_depend_map(join);
  return 0;
}
4762

unknown's avatar
unknown committed
4763

4764 4765 4766 4767 4768 4769 4770 4771 4772
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;
4773

4774
  /*  Use best key from find_best */
4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789
  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;
4790 4791 4792 4793 4794 4795
    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
    */
4796 4797
    do
    {
4798
      if (!(~used_tables & keyuse->used_tables))
unknown's avatar
unknown committed
4799
      {
4800 4801
	if (keyparts == keyuse->keypart &&
	    !(found_part_ref_or_null & keyuse->optimize))
unknown's avatar
unknown committed
4802
	{
4803
	  keyparts++;
4804 4805
	  length+= keyinfo->key_part[keyuse->keypart].store_length;
	  found_part_ref_or_null|= keyuse->optimize;
unknown's avatar
unknown committed
4806 4807
	}
      }
4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827
      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)))
  {
    return TRUE;
  }
  j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length);
  j->ref.key_err=1;
  keyuse=org_keyuse;

4828 4829
  store_key **ref_key= j->ref.key_copy;
  byte *key_buff=j->ref.key_buff, *null_ref_key= 0;
4830
  bool keyuse_uses_no_tables= TRUE;
4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849
  if (ftkey)
  {
    j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
    if (keyuse->used_tables)
      return TRUE; // not supported yet. SerG

    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
4850
      keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables;
4851 4852 4853
      if (!keyuse->used_tables &&
	  !(join->select_options & SELECT_DESCRIBE))
      {					// Compare against constant
unknown's avatar
unknown committed
4854 4855 4856 4857
	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);
4858
	if (thd->is_fatal_error)
4859
	  return TRUE;
unknown's avatar
unknown committed
4860
	tmp.copy();
unknown's avatar
unknown committed
4861 4862
      }
      else
4863 4864 4865 4866
	*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
4867 4868 4869 4870 4871 4872
      /*
	Remeber if we are going to use REF_OR_NULL
	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)
4873
	null_ref_key= key_buff;
4874
      key_buff+=keyinfo->key_part[i].store_length;
unknown's avatar
unknown committed
4875
    }
4876 4877
  } /* not ftkey */
  *ref_key=0;				// end_marker
4878 4879 4880 4881
  if (j->type == JT_FT)
    return 0;
  if (j->type == JT_CONST)
    j->table->const_table= 1;
4882
  else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
unknown's avatar
unknown committed
4883
			       HA_END_SPACE_KEY)) != HA_NOSAME) ||
unknown's avatar
unknown committed
4884
	   keyparts != keyinfo->key_parts || null_ref_key)
4885 4886 4887
  {
    /* Must read with repeat */
    j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
unknown's avatar
af  
unknown committed
4888
    j->ref.null_ref_key= null_ref_key;
4889
  }
4890
  else if (keyuse_uses_no_tables)
4891
  {
4892 4893 4894 4895 4896 4897 4898 4899
    /*
      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
4900
  }
4901 4902
  else
    j->type=JT_EQ_REF;
unknown's avatar
unknown committed
4903 4904 4905 4906
  return 0;
}


4907

unknown's avatar
unknown committed
4908
static store_key *
unknown's avatar
unknown committed
4909 4910
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
4911 4912 4913
{
  if (!((~used_tables) & keyuse->used_tables))		// if const item
  {
unknown's avatar
unknown committed
4914 4915
    return new store_key_const_item(thd,
				    key_part->field,
unknown's avatar
unknown committed
4916 4917 4918 4919 4920 4921
				    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
4922 4923
    return new store_key_field(thd,
			       key_part->field,
unknown's avatar
unknown committed
4924 4925 4926 4927 4928
			       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
4929 4930
  return new store_key_item(thd,
			    key_part->field,
unknown's avatar
unknown committed
4931 4932 4933 4934 4935 4936 4937
			    key_buff + maybe_null,
			    maybe_null ? key_buff : 0,
			    key_part->length,
			    keyuse->val);
}

/*
4938 4939
  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
4940 4941 4942 4943 4944
*/

bool
store_val_in_field(Field *field,Item *item)
{
4945
  bool error;
unknown's avatar
unknown committed
4946
  THD *thd=current_thd;
4947
  ha_rows cuted_fields=thd->cuted_fields;
unknown's avatar
af  
unknown committed
4948 4949 4950 4951 4952 4953
  /*
    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;
4954
  thd->count_cuted_fields= CHECK_FIELD_WARN;
4955
  error= item->save_in_field(field, 1);
unknown's avatar
af  
unknown committed
4956
  thd->count_cuted_fields= old_count_cuted_fields;
4957
  return error || cuted_fields != thd->cuted_fields;
unknown's avatar
unknown committed
4958 4959 4960 4961 4962 4963 4964 4965 4966
}


static bool
make_simple_join(JOIN *join,TABLE *tmp_table)
{
  TABLE **tableptr;
  JOIN_TAB *join_tab;

4967 4968
  if (!(tableptr=(TABLE**) join->thd->alloc(sizeof(TABLE*))) ||
      !(join_tab=(JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
unknown's avatar
unknown committed
4969 4970 4971 4972 4973 4974
    return TRUE;
  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
4975 4976 4977
  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
4978
  join->first_record=join->sort_and_group=0;
unknown's avatar
unknown committed
4979
  join->send_records=(ha_rows) 0;
unknown's avatar
unknown committed
4980
  join->group=0;
unknown's avatar
unknown committed
4981
  join->row_limit=join->unit->select_limit_cnt;
unknown's avatar
unknown committed
4982
  join->do_send_rows = (join->row_limit) ? 1 : 0;
unknown's avatar
unknown committed
4983

unknown's avatar
unknown committed
4984
  join_tab->cache.buff=0;			/* No caching */
unknown's avatar
unknown committed
4985 4986 4987 4988 4989
  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
4990
  join_tab->keys.init(~0);                      /* test everything in quick */
unknown's avatar
unknown committed
4991
  join_tab->info=0;
unknown's avatar
unknown committed
4992
  join_tab->on_expr_ref=0;
4993 4994
  join_tab->last_inner= 0;
  join_tab->first_unmatched= 0;
unknown's avatar
unknown committed
4995
  join_tab->ref.key = -1;
unknown's avatar
unknown committed
4996 4997
  join_tab->not_used_in_distinct=0;
  join_tab->read_first_record= join_init_read_record;
4998
  join_tab->join=join;
unknown's avatar
unknown committed
4999
  bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
unknown's avatar
unknown committed
5000 5001 5002 5003 5004 5005
  tmp_table->status=0;
  tmp_table->null_row=0;
  return FALSE;
}


5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035
/*
  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
5036
  if (tmp)
unknown's avatar
unknown committed
5037
    tmp->quick_fix_field();
5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060
  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
5061
    corresponding first inner table through the field t0->on_expr_ref.
5062 5063 5064
    Here ti are structures of the JOIN_TAB type.

  EXAMPLE
unknown's avatar
unknown committed
5065
    For the query: 
5066 5067 5068 5069 5070 5071 5072 5073 5074
      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
5075 5076
    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.
5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087
            
  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)
{
5088
  DBUG_ENTER("make_outerjoin_info");
5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103
  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
5104 5105
      tab->on_expr_ref= &tbl->on_expr;
      tab->cond_equal= tbl->cond_equal;
5106 5107 5108
      if (embedding)
        tab->first_upper= embedding->nested_join->first_nested;
    }    
unknown's avatar
unknown committed
5109
    for ( ; embedding ; embedding= embedding->embedding)
5110 5111 5112 5113 5114 5115 5116 5117 5118
    {
      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
5119 5120
        tab->on_expr_ref= &embedding->on_expr;
        tab->cond_equal= tbl->cond_equal;
5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131
        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;
    }
  }
5132
  DBUG_VOID_RETURN;
5133 5134 5135
}


unknown's avatar
unknown committed
5136 5137 5138 5139 5140 5141 5142
static bool
make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
{
  DBUG_ENTER("make_join_select");
  if (select)
  {
    table_map used_tables;
5143
    if (cond)                /* Because of QUICK_GROUP_MIN_MAX_SELECT */
unknown's avatar
unknown committed
5144
    {                        /* there may be a select without a cond. */    
5145 5146 5147
      if (join->tables > 1)
        cond->update_used_tables();		// Tablenr may have changed
      if (join->const_tables == join->tables &&
5148 5149
	  join->thd->lex->current_select->master_unit() ==
	  &join->thd->lex->unit)		// not upper level SELECT
5150 5151 5152
        join->const_table_map|=RAND_TABLE_BIT;
      {						// Check const tables
        COND *const_cond=
5153
	  make_cond_for_table(cond,join->const_table_map,(table_map) 0);
5154
        DBUG_EXECUTE("where",print_where(const_cond,"constants"););
5155 5156 5157
        for (JOIN_TAB *tab= join->join_tab+join->const_tables;
             tab < join->join_tab+join->tables ; tab++)
        {
5158
          if (*tab->on_expr_ref)
5159 5160
          {
            JOIN_TAB *cond_tab= tab->first_inner;
5161
            COND *tmp= make_cond_for_table(*tab->on_expr_ref,
5162
                                           join->const_table_map,
5163
                                         (  table_map) 0);
5164 5165 5166 5167 5168 5169 5170
            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 :
5171
	                            new Item_cond_and(cond_tab->select_cond,tmp);
5172
            if (!cond_tab->select_cond)
5173
	      DBUG_RETURN(1);
5174
            cond_tab->select_cond->quick_fix_field();
5175
          }       
5176
        }
5177 5178
        if (const_cond && !const_cond->val_int())
        {
5179
	  DBUG_PRINT("info",("Found impossible WHERE condition"));
unknown's avatar
unknown committed
5180
	  DBUG_RETURN(1);	 // Impossible const condition
5181
        }
5182
      }
unknown's avatar
unknown committed
5183
    }
unknown's avatar
unknown committed
5184 5185
    used_tables=((select->const_tables=join->const_table_map) |
		 OUTER_REF_TABLE_BIT | RAND_TABLE_BIT);
unknown's avatar
unknown committed
5186 5187 5188
    for (uint i=join->const_tables ; i < join->tables ; i++)
    {
      JOIN_TAB *tab=join->join_tab+i;
5189
      JOIN_TAB *first_inner_tab= tab->first_inner; 
unknown's avatar
unknown committed
5190
      table_map current_map= tab->table->map;
5191
      bool use_quick_range=0;
unknown's avatar
unknown committed
5192 5193 5194 5195
      /*
	Following force including random expression in last table condition.
	It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
      */
5196
      if (i == join->tables-1)
unknown's avatar
unknown committed
5197
	current_map|= OUTER_REF_TABLE_BIT | RAND_TABLE_BIT;
unknown's avatar
unknown committed
5198
      used_tables|=current_map;
5199 5200

      if (tab->type == JT_REF && tab->quick &&
unknown's avatar
unknown committed
5201
	  (uint) tab->ref.key == tab->quick->index &&
5202 5203 5204 5205 5206 5207
	  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
5208
        tab->ref.key= -1;
5209
	tab->ref.key_parts=0;		// Don't use ref key.
5210
	join->best_positions[i].records_read= rows2double(tab->quick->records);
5211 5212
      }

5213 5214 5215 5216
      COND *tmp= NULL;
      if (cond)
        tmp= make_cond_for_table(cond,used_tables,current_map);
      if (cond && !tmp && tab->quick)
5217
      {						// Outer join
5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234
        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.
          */
5235
          DBUG_PRINT("info", ("Item_int"));
5236
          tmp= new Item_int((longlong) 1,1);	// Always true
5237
          DBUG_PRINT("info", ("Item_int 0x%lx", (ulong)tmp));
5238 5239
        }

5240
      }
5241
      if (tmp || !cond)
unknown's avatar
unknown committed
5242
      {
5243
	DBUG_EXECUTE("where",print_where(tmp,tab->table->table_name););
unknown's avatar
unknown committed
5244
	SQL_SELECT *sel=tab->select=(SQL_SELECT*)
5245
	  join->thd->memdup((gptr) select, sizeof(SQL_SELECT));
unknown's avatar
unknown committed
5246 5247
	if (!sel)
	  DBUG_RETURN(1);			// End of memory
5248 5249 5250 5251 5252
        /*
          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.
5253
	*/        
5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264
        if (cond)
        {/*
            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;
        }
        else
          tab->select_cond= sel->cond= NULL;
5265

unknown's avatar
unknown committed
5266 5267 5268
	sel->head=tab->table;
	if (tab->quick)
	{
5269 5270
	  /* Use quick key read if it's a constant and it's not used
	     with key reading */
5271
	  if (tab->needed_reg.is_clear_all() && tab->type != JT_EQ_REF
5272
	      && tab->type != JT_FT && (tab->type != JT_REF ||
unknown's avatar
unknown committed
5273
               (uint) tab->ref.key == tab->quick->index))
unknown's avatar
unknown committed
5274 5275
	  {
	    sel->quick=tab->quick;		// Use value from get_quick_...
5276 5277
	    sel->quick_keys.clear_all();
	    sel->needed_reg.clear_all();
unknown's avatar
unknown committed
5278 5279 5280 5281 5282 5283 5284 5285 5286 5287
	  }
	  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)
	{
5288 5289
	  if (!tab->const_keys.is_clear_all() &&
              tab->table->reginfo.impossible_range)
unknown's avatar
unknown committed
5290 5291
	    DBUG_RETURN(1);
	}
5292
	else if (tab->type == JT_ALL && ! use_quick_range)
unknown's avatar
unknown committed
5293
	{
5294
	  if (!tab->const_keys.is_clear_all() &&
unknown's avatar
unknown committed
5295 5296 5297 5298
	      tab->table->reginfo.impossible_range)
	    DBUG_RETURN(1);				// Impossible range
	  /*
	    We plan to scan all rows.
5299 5300 5301
	    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
5302 5303
	  */

5304 5305
	  if (cond &&
              (!tab->keys.is_subset(tab->const_keys) && i > 0) ||
5306 5307
	      (!tab->const_keys.is_clear_all() && i == join->const_tables &&
	       join->unit->select_limit_cnt <
5308
	       join->best_positions[i].records_read &&
5309
	       !(join->select_options & OPTION_FOUND_ROWS)))
unknown's avatar
unknown committed
5310
	  {
5311 5312
	    /* Join with outer join condition */
	    COND *orig_cond=sel->cond;
unknown's avatar
unknown committed
5313
	    sel->cond= and_conds(sel->cond, *tab->on_expr_ref);
5314 5315 5316 5317 5318 5319 5320 5321

	    /*
              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
5322
	    if (sel->cond && !sel->cond->fixed)
5323 5324
	      sel->cond->quick_fix_field();

5325
	    if (sel->test_quick_select(join->thd, tab->keys,
unknown's avatar
unknown committed
5326
				       used_tables & ~ current_map,
5327 5328 5329
				       (join->select_options &
					OPTION_FOUND_ROWS ?
					HA_POS_ERROR :
5330
					join->unit->select_limit_cnt)) < 0)
unknown's avatar
unknown committed
5331 5332 5333 5334 5335
            {
	      /*
		Before reporting "Impossible WHERE" for the whole query
		we have to check isn't it only "impossible ON" instead
	      */
5336
              sel->cond=orig_cond;
unknown's avatar
unknown committed
5337
              if (!*tab->on_expr_ref ||
5338
                  sel->test_quick_select(join->thd, tab->keys,
5339 5340 5341 5342
                                         used_tables & ~ current_map,
                                         (join->select_options &
                                          OPTION_FOUND_ROWS ?
                                          HA_POS_ERROR :
unknown's avatar
unknown committed
5343 5344
                                          join->unit->select_limit_cnt)) < 0)
		DBUG_RETURN(1);			// Impossible WHERE
5345 5346 5347 5348
            }
            else
	      sel->cond=orig_cond;

5349 5350 5351
	    /* Fix for EXPLAIN */
	    if (sel->quick)
	      join->best_positions[i].records_read= sel->quick->records;
unknown's avatar
unknown committed
5352 5353 5354 5355
	  }
	  else
	  {
	    sel->needed_reg=tab->needed_reg;
5356
	    sel->quick_keys.clear_all();
unknown's avatar
unknown committed
5357
	  }
5358 5359
	  if (!sel->quick_keys.is_subset(tab->checked_keys) ||
              !sel->needed_reg.is_subset(tab->checked_keys))
unknown's avatar
unknown committed
5360
	  {
5361 5362 5363 5364
	    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
5365 5366 5367
			      (select->quick &&
			       (select->quick->records >= 100L)))) ?
	      2 : 1;
unknown's avatar
unknown committed
5368
	    sel->read_tables= used_tables & ~current_map;
unknown's avatar
unknown committed
5369 5370 5371
	  }
	  if (i != join->const_tables && tab->use_quick != 2)
	  {					/* Read with cache */
5372 5373
	    if (cond &&
                (tmp=make_cond_for_table(cond,
unknown's avatar
unknown committed
5374 5375 5376 5377 5378
					 join->const_table_map |
					 current_map,
					 current_map)))
	    {
	      DBUG_EXECUTE("where",print_where(tmp,"cache"););
5379 5380
	      tab->cache.select=(SQL_SELECT*)
		join->thd->memdup((gptr) sel, sizeof(SQL_SELECT));
unknown's avatar
unknown committed
5381 5382 5383 5384 5385
	      tab->cache.select->cond=tmp;
	      tab->cache.select->read_tables=join->const_table_map;
	    }
	  }
	}
5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402
      } 
      
      /* 
        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
5403
        COND *on_expr= *first_inner_tab->on_expr_ref;
5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425

        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.
	    */ 
5426
            DBUG_PRINT("info", ("Item_func_trig_cond"));
5427 5428
            tmp= new Item_func_trig_cond(tmp, 
                                         &first_inner_tab->not_null_compl);
5429
            DBUG_PRINT("info", ("Item_func_trig_cond 0x%lx", (ulong) tmp));
unknown's avatar
unknown committed
5430 5431
            if (tmp)
              tmp->quick_fix_field();
5432
	    /* Add the predicate to other pushed down predicates */
5433
            DBUG_PRINT("info", ("Item_cond_and"));
5434 5435
            cond_tab->select_cond= !cond_tab->select_cond ? tmp :
	                          new Item_cond_and(cond_tab->select_cond,tmp);
5436 5437
            DBUG_PRINT("info", ("Item_cond_and 0x%lx",
                                (ulong)cond_tab->select_cond));
5438 5439
            if (!cond_tab->select_cond)
	      DBUG_RETURN(1);
unknown's avatar
unknown committed
5440
            cond_tab->select_cond->quick_fix_field();
5441 5442 5443
          }              
        }
        first_inner_tab= first_inner_tab->first_upper;       
unknown's avatar
unknown committed
5444 5445 5446 5447 5448 5449 5450
      }
    }
  }
  DBUG_RETURN(0);
}

static void
5451
make_join_readinfo(JOIN *join, uint options)
unknown's avatar
unknown committed
5452 5453
{
  uint i;
5454

unknown's avatar
af  
unknown committed
5455
  bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
unknown's avatar
unknown committed
5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474
  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
5475 5476 5477 5478 5479 5480
      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
5481 5482 5483
      break;
    case JT_EQ_REF:
      table->status=STATUS_NO_RECORD;
5484 5485 5486 5487 5488
      if (tab->select)
      {
	delete tab->select->quick;
	tab->select->quick=0;
      }
unknown's avatar
unknown committed
5489 5490 5491 5492
      delete tab->quick;
      tab->quick=0;
      tab->read_first_record= join_read_key;
      tab->read_record.read_record= join_no_more_records;
5493
      if (table->used_keys.is_set(tab->ref.key) &&
unknown's avatar
unknown committed
5494
	  !table->no_keyread)
unknown's avatar
unknown committed
5495 5496 5497 5498 5499
      {
	table->key_read=1;
	table->file->extra(HA_EXTRA_KEYREAD);
      }
      break;
5500
    case JT_REF_OR_NULL:
unknown's avatar
unknown committed
5501 5502
    case JT_REF:
      table->status=STATUS_NO_RECORD;
5503 5504 5505 5506 5507
      if (tab->select)
      {
	delete tab->select->quick;
	tab->select->quick=0;
      }
unknown's avatar
unknown committed
5508 5509
      delete tab->quick;
      tab->quick=0;
5510
      if (table->used_keys.is_set(tab->ref.key) &&
unknown's avatar
unknown committed
5511
	  !table->no_keyread)
unknown's avatar
unknown committed
5512 5513 5514 5515
      {
	table->key_read=1;
	table->file->extra(HA_EXTRA_KEYREAD);
      }
5516 5517 5518 5519 5520 5521 5522 5523 5524 5525
      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
5526 5527 5528 5529 5530 5531 5532 5533
      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:
      /*
5534
	If previous table use cache
unknown's avatar
unknown committed
5535 5536
      */
      table->status=STATUS_NO_RECORD;
unknown's avatar
unknown committed
5537
      if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
5538
          tab->use_quick != 2 && !tab->first_inner)
unknown's avatar
unknown committed
5539 5540 5541 5542 5543 5544 5545 5546 5547 5548
      {
	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)
5549
      {
5550
	join->thd->server_status|=SERVER_QUERY_NO_GOOD_INDEX_USED;
unknown's avatar
unknown committed
5551
	tab->read_first_record= join_init_quick_read_record;
unknown's avatar
af  
unknown committed
5552
	if (statistics)
5553 5554
	  statistic_increment(join->thd->status_var.select_range_check_count,
			      &LOCK_status);
5555
      }
unknown's avatar
unknown committed
5556 5557 5558
      else
      {
	tab->read_first_record= join_init_read_record;
5559 5560 5561 5562
	if (i == join->const_tables)
	{
	  if (tab->select && tab->select->quick)
	  {
unknown's avatar
af  
unknown committed
5563
	    if (statistics)
5564 5565
	      statistic_increment(join->thd->status_var.select_range_count,
				  &LOCK_status);
5566 5567 5568
	  }
	  else
	  {
5569
	    join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
unknown's avatar
af  
unknown committed
5570
	    if (statistics)
5571 5572
	      statistic_increment(join->thd->status_var.select_scan_count,
				  &LOCK_status);
5573 5574 5575 5576 5577 5578
	  }
	}
	else
	{
	  if (tab->select && tab->select->quick)
	  {
unknown's avatar
af  
unknown committed
5579
	    if (statistics)
5580 5581
	      statistic_increment(join->thd->status_var.select_full_range_join_count,
				  &LOCK_status);
5582 5583 5584
	  }
	  else
	  {
5585
	    join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
unknown's avatar
af  
unknown committed
5586
	    if (statistics)
5587 5588
	      statistic_increment(join->thd->status_var.select_full_join_count,
				  &LOCK_status);
5589 5590
	  }
	}
unknown's avatar
unknown committed
5591
	if (!table->no_keyread)
unknown's avatar
unknown committed
5592
	{
unknown's avatar
unknown committed
5593
	  if (tab->select && tab->select->quick &&
5594
	      table->used_keys.is_set(tab->select->quick->index))
unknown's avatar
unknown committed
5595 5596 5597 5598
	  {
	    table->key_read=1;
	    table->file->extra(HA_EXTRA_KEYREAD);
	  }
unknown's avatar
af  
unknown committed
5599 5600
	  else if (!table->used_keys.is_clear_all() &&
		   !(tab->select && tab->select->quick))
unknown's avatar
unknown committed
5601
	  {					// Only read index tree
unknown's avatar
unknown committed
5602
	    tab->index=find_shortest_key(table, & table->used_keys);
5603
	    tab->read_first_record= join_read_first;
unknown's avatar
unknown committed
5604 5605
	    tab->type=JT_NEXT;		// Read with index_first / index_next
	  }
unknown's avatar
unknown committed
5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621
	}
      }
      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
5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643
/*
  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++)
  {
5644
    if (tab->type == JT_ALL && (!tab->select || !tab->select->quick))
unknown's avatar
unknown committed
5645
    {
unknown's avatar
unknown committed
5646 5647
      my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
                 ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
unknown's avatar
unknown committed
5648 5649 5650 5651 5652 5653 5654
      return(1);
    }
  }
  return(0);
}


unknown's avatar
af  
unknown committed
5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676
/*
  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
5677
    table->file->ha_index_or_rnd_end();
unknown's avatar
af  
unknown committed
5678 5679 5680 5681 5682 5683 5684 5685 5686 5687
    /*
      We need to reset this for next select
      (Tested in part_of_refkey)
    */
    table->reginfo.join_tab= 0;
  }
  end_read_record(&read_record);
}


5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700
/*
  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
5701 5702
{
  JOIN_TAB *tab,*end;
unknown's avatar
unknown committed
5703
  DBUG_ENTER("JOIN::join_free");
unknown's avatar
unknown committed
5704

5705
  full= full || !select_lex->uncacheable;
unknown's avatar
unknown committed
5706

5707
  if (table)
unknown's avatar
unknown committed
5708
  {
5709 5710 5711 5712
    /*
      Only a sorted table may be cached.  This sorted table is always the
      first non const table in join->table
    */
5713
    if (tables > const_tables) // Test for not-const tables
unknown's avatar
unknown committed
5714
    {
5715 5716
      free_io_cache(table[const_tables]);
      filesort_free_buffers(table[const_tables]);
unknown's avatar
unknown committed
5717
    }
5718 5719 5720

    for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); unit;
         unit= unit->next_unit())
5721
    {
5722 5723 5724 5725 5726
      JOIN *join;
      for (SELECT_LEX *sl= unit->first_select_in_union(); sl;
           sl= sl->next_select())
        if ((join= sl->join))
          join->join_free(full);
5727
    }
5728 5729

    if (full)
unknown's avatar
unknown committed
5730
    {
5731
      for (tab= join_tab, end= tab+tables; tab != end; tab++)
unknown's avatar
af  
unknown committed
5732
	tab->cleanup();
5733
      table= 0;
unknown's avatar
unknown committed
5734
    }
unknown's avatar
unknown committed
5735
    else
5736
    {
5737
      for (tab= join_tab, end= tab+tables; tab != end; tab++)
unknown's avatar
unknown committed
5738
      {
5739 5740
	if (tab->table)
	    tab->table->file->ha_index_or_rnd_end();
unknown's avatar
unknown committed
5741
      }
5742
    }
unknown's avatar
unknown committed
5743
  }
5744

5745 5746 5747 5748
  /*
    We are not using tables anymore
    Unlock all tables. We may be in an INSERT .... SELECT statement.
  */
unknown's avatar
unknown committed
5749
  if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK) &&
5750
      !select_lex->subquery_in_having)
unknown's avatar
unknown committed
5751
  {
5752 5753 5754 5755 5756 5757 5758
    // 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
5759
  }
5760

5761 5762
  if (full)
  {
5763
    group_fields.delete_elements();
5764 5765 5766 5767
    /*
      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
5768
    tmp_table_param.copy_funcs.empty();
5769
    tmp_table_param.cleanup();
5770
  }
unknown's avatar
unknown committed
5771
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
5772 5773 5774 5775
}


/*****************************************************************************
5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788
  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
5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812
*****************************************************************************/

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)
      {
5813
	if ((*ref_item)->eq(order->item[0],0))
unknown's avatar
unknown committed
5814 5815 5816 5817 5818
	  break;
      }
      if (order)
      {
	found++;
unknown's avatar
unknown committed
5819
	DBUG_ASSERT(!(order->used & map));
unknown's avatar
unknown committed
5820 5821 5822 5823 5824 5825 5826 5827
	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 */
5828
  for (; found && start_order ; start_order=start_order->next)
unknown's avatar
unknown committed
5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845
  {
    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)
5846
    return 0;			// skip this optimize /* purecov: inspected */
unknown's avatar
unknown committed
5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861
  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;

5862
  for (; join_tab != end ; join_tab++)
unknown's avatar
unknown committed
5863 5864 5865 5866 5867 5868 5869
  {
    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
5870
    ref->depend_map=depend_map & ~OUTER_REF_TABLE_BIT;
5871
    depend_map&= ~OUTER_REF_TABLE_BIT;
5872
    for (JOIN_TAB **tab=join->map2table;
unknown's avatar
unknown committed
5873
	 depend_map ;
5874
	 tab++,depend_map>>=1 )
unknown's avatar
unknown committed
5875 5876
    {
      if (depend_map & 1)
5877
	ref->depend_map|=(*tab)->ref.depend_map;
unknown's avatar
unknown committed
5878 5879 5880 5881 5882 5883 5884 5885 5886
    }
  }
}


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

static void update_depend_map(JOIN *join, ORDER *order)
{
5887
  for (; order ; order=order->next)
unknown's avatar
unknown committed
5888 5889 5890 5891
  {
    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
5892 5893
    // 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
5894
    {
5895
      for (JOIN_TAB **tab=join->map2table;
unknown's avatar
unknown committed
5896
	   depend_map ;
5897
	   tab++, depend_map>>=1)
unknown's avatar
unknown committed
5898 5899
      {
	if (depend_map & 1)
5900
	  order->depend_map|=(*tab)->ref.depend_map;
unknown's avatar
unknown committed
5901 5902 5903 5904 5905 5906 5907
      }
    }
  }
}


/*
unknown's avatar
unknown committed
5908 5909
  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
5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922
*/

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
5923
  *simple_order= *join->join_tab[join->const_tables].on_expr_ref ? 0 : 1;
unknown's avatar
unknown committed
5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935

  /* 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
5936
      continue;					// skip const item
unknown's avatar
unknown committed
5937 5938 5939
    }
    else
    {
unknown's avatar
unknown committed
5940
      if (order_tables & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951
	*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)))
	{
5952
	  if (!(order_tables & first_table) && only_eq_ref_tables(join,first_order,ref))
unknown's avatar
unknown committed
5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970
	  {
	    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);
}

5971

unknown's avatar
unknown committed
5972
static int
5973 5974
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
5975 5976
		 const char *info, Item *having, Procedure *procedure,
		 SELECT_LEX_UNIT *unit)
unknown's avatar
unknown committed
5977 5978 5979 5980
{
  DBUG_ENTER("return_zero_rows");

  if (select_options & SELECT_DESCRIBE)
5981
  {
unknown's avatar
af  
unknown committed
5982
    select_describe(join, FALSE, FALSE, FALSE, info);
unknown's avatar
unknown committed
5983 5984
    DBUG_RETURN(0);
  }
unknown's avatar
unknown committed
5985

5986 5987
  join->join_free(0);

unknown's avatar
unknown committed
5988 5989
  if (send_row)
  {
5990
    for (TABLE_LIST *table= tables; table; table= table->next_leaf)
unknown's avatar
unknown committed
5991
      mark_as_null_row(table->table);		// All fields are NULL
5992
    if (having && having->val_int() == 0)
unknown's avatar
unknown committed
5993 5994
      send_row=0;
  }
5995 5996
  if (!(result->send_fields(fields,
                              Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)))
unknown's avatar
unknown committed
5997 5998
  {
    if (send_row)
unknown's avatar
unknown committed
5999 6000 6001 6002 6003
    {
      List_iterator_fast<Item> it(fields);
      Item *item;
      while ((item= it++))
	item->no_rows_in_result();
unknown's avatar
unknown committed
6004
      result->send_data(fields);
unknown's avatar
unknown committed
6005
    }
6006
    result->send_eof();				// Should be safe
unknown's avatar
unknown committed
6007
  }
6008 6009
  /* Update results for FOUND_ROWS */
  join->thd->limit_found_rows= join->thd->examined_row_count= 0;
unknown's avatar
unknown committed
6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020
  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
}

/*****************************************************************************
6021 6022 6023 6024 6025 6026
  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
6027 6028 6029 6030
*****************************************************************************/

class COND_CMP :public ilink {
public:
unknown's avatar
unknown committed
6031 6032 6033 6034
  static void *operator new(size_t size)
  {
    return (void*) sql_alloc((uint) size);
  }
unknown's avatar
unknown committed
6035
  static void operator delete(void *ptr __attribute__((unused)),
unknown's avatar
unknown committed
6036 6037
                              size_t size __attribute__((unused)))
  { TRASH(ptr, size); }
unknown's avatar
unknown committed
6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050

  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

6051 6052 6053 6054 6055 6056 6057 6058

/* 
  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
6059
    inherited_fl  :out  set up to TRUE if multiple equality is found
6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086
                        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
6087
    cond_equal= cond_equal->upper_levels;
6088 6089 6090
  }
  in_upper_level= FALSE;
finish:
unknown's avatar
unknown committed
6091
  *inherited_fl= in_upper_level;
6092 6093
  return item;
}
unknown's avatar
unknown committed
6094

6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106
  
/* 
  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
6107 6108
    the one that equates a field with another field or a constant
    (item=constant_item or item=field_item).
6109
    If this is the case the function looks a for a multiple equality
unknown's avatar
unknown committed
6110 6111 6112 6113 6114 6115 6116 6117 6118
    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
6119 6120
    be minimal.

unknown's avatar
unknown committed
6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135
  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),[])
    and will transform *cond_equal into (ptr(CE,[Item_equal(2,a,b,c)]).
    For f=e it will be called with *cond_equal=(ptr(CE), [])
    and will transform *cond_equal into (ptr(CE,[Item_equal(f,e)]).

6136 6137 6138 6139
  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
6140
    can be used in the constant propagation procedure.
6141 6142 6143 6144 6145 6146
    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
6147
    to build_equal_items_for_cond.
6148 6149 6150 6151 6152 6153
    
  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
6154
    field2. If only one of them is found the fuction expands it with
6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191
    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
6192
      if (left_field->eq(right_field))  /* f = f */
6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205
        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
6206 6207
           multiple equalities, i.e the condition is already covered
           by upper level equalities
6208 6209 6210 6211 6212 6213 6214
        */
          return TRUE;
      }
      
      /* Copy the found multiple equalities at the current level if needed */
      if (left_copyfl)
      {
unknown's avatar
unknown committed
6215
        /* left_item_equal of an upper level contains left_item */
6216 6217 6218 6219 6220
        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
6221
        /* right_item_equal of an upper level contains right_item */
6222 6223 6224 6225 6226 6227
        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
6228
        /* left item was found in the current or one of the upper levels */
6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242
        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
6243
        /* left item was not found neither the current nor in upper levels  */
6244 6245 6246 6247
         if (right_item_equal)
           right_item_equal->add((Item_field *) left_item);
         else 
         {
unknown's avatar
unknown committed
6248
           /* None of the fields was found in multiple equalities */
6249 6250 6251 6252 6253 6254 6255
           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
6256

6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276
    {
      /* 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
6277 6278

        if (field_item->result_type() == STRING_RESULT &&
unknown's avatar
unknown committed
6279
              ((Field_str *) field_item->field)->charset() !=
unknown's avatar
unknown committed
6280 6281 6282
               ((Item_cond *) item)->compare_collation())
          return FALSE;

6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314
        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
6315
    build_equal_items_for_cond()
6316 6317 6318 6319 6320 6321 6322 6323 6324
    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
6325 6326 6327 6328 6329
    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
6330
    is any. If this multiple equality equates fields to a constant the
unknown's avatar
unknown committed
6331 6332 6333 6334 6335
    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.  
6336 6337 6338 6339 6340 6341 6342

  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
6343
    The function always makes a substitution of all equality predicates occured
6344 6345 6346 6347 6348 6349
    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
6350
    while (t1.a=t2.b AND t2.b>5 AND t3.c=t4.d) is replaced by
6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363
    (=(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
6364 6365 6366 6367 6368 6369 6370
    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.
6371 6372 6373 6374 6375

  RETURN
    pointer to the transformed condition
*/

unknown's avatar
unknown committed
6376
static COND *build_equal_items_for_cond(COND *cond,
6377 6378
                                        COND_EQUAL *inherited)
{
unknown's avatar
unknown committed
6379 6380
  Item_equal *item_equal;
  uint members;
6381
  COND_EQUAL cond_equal;
unknown's avatar
unknown committed
6382
  cond_equal.upper_levels= inherited;
6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397

  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
6398
         removing each such predicate from the conjunction after having 
6399 6400 6401 6402 6403 6404 6405 6406 6407
         found/created a multiple equality whose inference the predicate is.
     */      
      while ((item= li++))
      {
        if (check_equality(item, &cond_equal))
          li.remove();
      }

      List_iterator_fast<Item_equal> it(cond_equal.current_level);
unknown's avatar
unknown committed
6408
      while ((item_equal= it++))
6409
      {
unknown's avatar
unknown committed
6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426
        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);
      }

6427 6428 6429 6430 6431 6432 6433
      ((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
6434 6435
    li.rewind();
    while((item= li++))
6436 6437
    { 
      Item *new_item;
unknown's avatar
unknown committed
6438
      if ((new_item = build_equal_items_for_cond(item, inherited))!= item)
6439 6440
      {
        /* This replacement happens only for standalone equalities */
unknown's avatar
unknown committed
6441
        li.replace(new_item);
6442 6443 6444 6445 6446 6447 6448
      }
    }
    if (and_level)
      args->concat((List<Item> *)&cond_equal.current_level);
  }
  else if (cond->type() == Item::FUNC_ITEM)
  {
unknown's avatar
unknown committed
6449 6450 6451 6452 6453 6454 6455 6456 6457 6458
    /*
      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).  
     */
6459 6460 6461
    if (check_equality(cond, &cond_equal) &&
        (item_equal= cond_equal.current_level.pop()))
    {
unknown's avatar
unknown committed
6462 6463
      item_equal->fix_length_and_dec();
      item_equal->update_used_tables();
6464 6465
      return item_equal;
    }
unknown's avatar
unknown committed
6466 6467 6468 6469 6470 6471 6472
    /* 
      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();
6473
  }
unknown's avatar
unknown committed
6474 6475 6476
  return cond;
}

unknown's avatar
unknown committed
6477

unknown's avatar
unknown committed
6478 6479 6480 6481 6482 6483
/* 
  Build multiple equalities for a condition and all on expressions that
  inherit these multiple equalities

  SYNOPSIS
    build_equal_items()
unknown's avatar
unknown committed
6484
    thd			Thread handler
unknown's avatar
unknown committed
6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 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 6527 6528 6529 6530 6531 6532 6533 6534 6535
    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
6536
static COND *build_equal_items(THD *thd, COND *cond,
unknown's avatar
unknown committed
6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572
                               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)
      {
unknown's avatar
unknown committed
6573
        Item *expr;
unknown's avatar
unknown committed
6574 6575
        List<TABLE_LIST> *join_list= table->nested_join ?
	                             &table->nested_join->join_list : NULL;
unknown's avatar
unknown committed
6576 6577 6578 6579
        expr= build_equal_items(thd, table->on_expr, inherited, join_list,
                                &table->cond_equal);
        if (expr != table->on_expr)
          thd->change_item_tree(&table->on_expr, expr);
unknown's avatar
unknown committed
6580 6581 6582 6583
      }
    }
  }

6584 6585 6586
  return cond;
}    

unknown's avatar
unknown committed
6587

unknown's avatar
unknown committed
6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631
/* 
  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);
}

6632 6633 6634 6635 6636 6637 6638

/* 
  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
6639
    upper_levels    structure to access multiple equality of upper levels
6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652
    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
6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666
    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.
6667 6668 6669 6670 6671
    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
6672 6673
    a pointer to the simple generated equality, if success.
    0, otherwise.
6674 6675
*/

unknown's avatar
unknown committed
6676
static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
6677 6678
                                  Item_equal *item_equal)
{
unknown's avatar
unknown committed
6679 6680
  List<Item> eq_list;
  Item_func_eq *eq_item= 0;
unknown's avatar
unknown committed
6681
  if (((Item *) item_equal)->const_item() && !item_equal->val_int())
unknown's avatar
unknown committed
6682
    return new Item_int((longlong) 0,1); 
6683 6684
  Item *item_const= item_equal->get_const();
  Item_equal_iterator it(*item_equal);
unknown's avatar
unknown committed
6685
  Item *head;
6686 6687 6688 6689 6690 6691 6692 6693 6694 6695
  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
6696
    Item_equal *upper= item_field->find_item_equal(upper_levels);
6697 6698 6699
    Item_field *item= item_field;
    if (upper)
    { 
unknown's avatar
unknown committed
6700 6701
      if (item_const && upper->get_const())
        item= 0;
6702 6703 6704 6705 6706
      else
      {
        Item_equal_iterator li(*item_equal);
        while ((item= li++) != item_field)
        {
unknown's avatar
unknown committed
6707
          if (item->find_item_equal(upper_levels) == upper)
6708 6709 6710 6711 6712 6713
            break;
        }
      }
    }
    if (item == item_field)
    {
unknown's avatar
unknown committed
6714 6715 6716 6717 6718 6719
      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
6720
      eq_item->quick_fix_field();
unknown's avatar
unknown committed
6721
   }
6722
  }
unknown's avatar
unknown committed
6723 6724

  if (!cond && !eq_list.head())
unknown's avatar
unknown committed
6725 6726 6727
  {
    if (!eq_item)
      return new Item_int((longlong) 1,1);
unknown's avatar
unknown committed
6728
    return eq_item;
unknown's avatar
unknown committed
6729
  }
unknown's avatar
unknown committed
6730

unknown's avatar
unknown committed
6731 6732
  if (eq_item)
    eq_list.push_back(eq_item);
6733
  if (!cond)
unknown's avatar
unknown committed
6734 6735 6736
    cond= new Item_cond_and(eq_list);
  else
    ((Item_cond *) cond)->add_at_head(&eq_list);
unknown's avatar
unknown committed
6737 6738 6739

  cond->quick_fix_field();
  cond->update_used_tables();
unknown's avatar
unknown committed
6740
   
6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751
  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
6752
    cond_equal      multiple equalities to take into consideration
6753 6754 6755 6756 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777
    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
6778
                                             COND_EQUAL *cond_equal,
6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794
                                             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
6795
      while ((item_equal= it++))
6796
      {
unknown's avatar
unknown committed
6797
        item_equal->sort(&compare_fields_by_table_order, table_join_idx);
6798 6799 6800 6801 6802 6803 6804
      }
    }
    
    List_iterator<Item> li(*cond_list);
    Item *item;
    while ((item= li++))
    {
unknown's avatar
unknown committed
6805
      Item *new_item =substitute_for_best_equal_field(item, cond_equal,
6806 6807 6808 6809 6810 6811 6812 6813
                                                        table_join_idx);
      if (new_item != item)
        li.replace(new_item);
   }

    if (and_level)
    {
      List_iterator_fast<Item_equal> it(cond_equal->current_level);
unknown's avatar
unknown committed
6814
      while ((item_equal= it++))
6815
      {
unknown's avatar
unknown committed
6816
        eliminate_item_equal(cond, cond_equal->upper_levels, item_equal);
6817 6818 6819 6820 6821 6822 6823
      }
    }
  }
  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
6824
    item_equal->sort(&compare_fields_by_table_order, table_join_idx);
unknown's avatar
unknown committed
6825 6826 6827
    if (cond_equal && cond_equal->current_level.head() == item_equal)
      cond_equal= 0;
    return eliminate_item_equal(0, cond_equal, item_equal);
6828 6829 6830 6831 6832 6833
  }
  else
    cond->walk(&Item::replace_equal_field_processor, 0);
  return cond;
}

unknown's avatar
unknown committed
6834

unknown's avatar
unknown committed
6835
/*
6836 6837
  change field = field to field = const for each found field = const in the
  and_level
unknown's avatar
unknown committed
6838 6839 6840
*/

static void
6841 6842 6843
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
6844 6845 6846 6847 6848 6849 6850 6851
{
  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++))
6852
      change_cond_ref_to_const(thd, save_list,and_level ? cond : item, item,
unknown's avatar
unknown committed
6853 6854 6855 6856 6857 6858 6859
			       field, value);
    return;
  }
  if (cond->eq_cmp_result() == Item::COND_OK)
    return;					// Not a boolean function

  Item_bool_func2 *func=  (Item_bool_func2*) cond;
6860 6861 6862
  Item **args= func->arguments();
  Item *left_item=  args[0];
  Item *right_item= args[1];
unknown's avatar
unknown committed
6863 6864
  Item_func::Functype functype=  func->functype();

6865 6866 6867 6868
  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
6869 6870 6871 6872
  {
    Item *tmp=value->new_item();
    if (tmp)
    {
6873
      thd->change_item_tree(args + 1, tmp);
unknown's avatar
unknown committed
6874 6875 6876 6877 6878 6879 6880 6881 6882
      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);
      }
6883
      func->set_cmp_func();
unknown's avatar
unknown committed
6884 6885
    }
  }
6886 6887 6888 6889
  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
6890 6891 6892 6893
  {
    Item *tmp=value->new_item();
    if (tmp)
    {
6894 6895
      thd->change_item_tree(args, tmp);
      value= tmp;
unknown's avatar
unknown committed
6896 6897 6898 6899
      func->update_used_tables();
      if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC)
	  && and_father != cond && !right_item->const_item())
      {
6900
        args[0]= args[1];                       // For easy check
6901
        thd->change_item_tree(args + 1, value);
unknown's avatar
unknown committed
6902 6903 6904 6905 6906
	cond->marker=1;
	COND_CMP *tmp2;
	if ((tmp2=new COND_CMP(and_father,func)))
	  save_list->push_back(tmp2);
      }
6907
      func->set_cmp_func();
unknown's avatar
unknown committed
6908 6909 6910 6911
    }
  }
}

6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944
/*
  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
6945 6946

static void
6947 6948
propagate_cond_constants(THD *thd, I_List<COND_CMP> *save_list,
                         COND *and_father, COND *cond)
unknown's avatar
unknown committed
6949 6950 6951 6952 6953
{
  if (cond->type() == Item::COND_ITEM)
  {
    bool and_level= ((Item_cond*) cond)->functype() ==
      Item_func::COND_AND_FUNC;
unknown's avatar
unknown committed
6954
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
6955 6956 6957 6958
    Item *item;
    I_List<COND_CMP> save;
    while ((item=li++))
    {
6959
      propagate_cond_constants(thd, &save,and_level ? cond : item, item);
unknown's avatar
unknown committed
6960 6961 6962 6963 6964 6965
    }
    if (and_level)
    {						// Handle other found items
      I_List_iterator<COND_CMP> cond_itr(save);
      COND_CMP *cond_cmp;
      while ((cond_cmp=cond_itr++))
6966 6967 6968 6969 6970 6971
      {
        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
6972 6973
    }
  }
6974
  else if (and_father != cond && !cond->marker)		// In a AND group
unknown's avatar
unknown committed
6975 6976 6977 6978 6979 6980
  {
    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;
6981 6982 6983
      Item **args= func->arguments();
      bool left_const= args[0]->const_item();
      bool right_const= args[1]->const_item();
6984
      if (!(left_const && right_const) &&
6985
          args[0]->result_type() == args[1]->result_type())
unknown's avatar
unknown committed
6986 6987 6988
      {
	if (right_const)
	{
6989
          resolve_const_item(thd, &args[1], args[0]);
unknown's avatar
unknown committed
6990
	  func->update_used_tables();
6991 6992
          change_cond_ref_to_const(thd, save_list, and_father, and_father,
                                   args[0], args[1]);
unknown's avatar
unknown committed
6993 6994 6995
	}
	else if (left_const)
	{
6996
          resolve_const_item(thd, &args[0], args[1]);
unknown's avatar
unknown committed
6997
	  func->update_used_tables();
6998 6999
          change_cond_ref_to_const(thd, save_list, and_father, and_father,
                                   args[1], args[0]);
unknown's avatar
unknown committed
7000 7001 7002 7003 7004 7005 7006
	}
      }
    }
  }
}


7007 7008 7009 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066 7067 7068 7069 7070
/*
  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.
7071
    E.g. SELECT * FROM t1, (t2, t3) WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b
7072
    finally is converted to: 
7073
      SELECT * FROM t1, t2, t3 WHERE t2.c < 5 AND t2.a=t1.a AND t3.b=t1.b
7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107

    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);
7108
  DBUG_ENTER("simplify_joins");
7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126

  /* 
    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
7127
        Item *expr;
7128 7129 7130 7131 7132 7133 7134 7135
        /* 
           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
7136 7137 7138
        expr= simplify_joins(join, &nested_join->join_list,
                             table->on_expr, FALSE);
        table->on_expr= expr;
7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157
      }
      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;
    }
7158 7159

    if (!table->outer_join || (used_tables & not_null_tables))
7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208
    {
      /* 
        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);
          conds->fix_fields(join->thd, 0, &conds);
        }
        else
          conds= table->on_expr; 
        table->on_expr= 0;
      }
    }
    
    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)
7209
      {
7210
        prev_table->dep_tables|= table->on_expr_dep_tables;
7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222
        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;
      }
7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243
    }
    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
7244
  DBUG_RETURN(conds); 
7245
}
unknown's avatar
unknown committed
7246
        
unknown's avatar
unknown committed
7247

unknown's avatar
unknown committed
7248
static COND *
unknown's avatar
unknown committed
7249 7250
optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list,
              Item::cond_result *cond_value)
unknown's avatar
unknown committed
7251
{
unknown's avatar
unknown committed
7252
  THD *thd= join->thd;
unknown's avatar
unknown committed
7253
  SELECT_LEX *select= thd->lex->current_select;    
7254 7255
  DBUG_ENTER("optimize_cond");

unknown's avatar
unknown committed
7256 7257 7258
  if (!conds)
  {
    *cond_value= Item::COND_TRUE;
7259 7260 7261 7262
    select->prep_where= 0;
  }
  else
  {
unknown's avatar
unknown committed
7263 7264 7265 7266 7267 7268 7269 7270
    /* 
      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.
    */ 
7271
    DBUG_EXECUTE("where", print_where(conds, "original"););
unknown's avatar
unknown committed
7272 7273 7274 7275
    conds= build_equal_items(join->thd, conds, NULL, join_list,
                             &join->cond_equal);
    DBUG_EXECUTE("where",print_where(conds,"after equal_items"););

7276
    /* change field = field to field = const for each found field = const */
7277
    propagate_cond_constants(thd, (I_List<COND_CMP> *) 0, conds, conds);
7278 7279 7280 7281 7282 7283 7284
    /*
      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
7285
  }
7286
  DBUG_RETURN(conds);
unknown's avatar
unknown committed
7287 7288 7289 7290
}


/*
7291 7292 7293 7294 7295
  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
7296 7297 7298
*/

static COND *
unknown's avatar
af  
unknown committed
7299
remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
unknown's avatar
unknown committed
7300 7301 7302 7303 7304 7305 7306
{
  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;
7307
    bool should_fix_fields=0;
unknown's avatar
unknown committed
7308 7309 7310 7311 7312

    *cond_value=Item::COND_UNDEF;
    Item *item;
    while ((item=li++))
    {
unknown's avatar
af  
unknown committed
7313
      Item *new_item=remove_eq_conds(thd, item, &tmp_cond_value);
unknown's avatar
unknown committed
7314 7315 7316 7317 7318
      if (!new_item)
	li.remove();
      else if (item != new_item)
      {
	VOID(li.replace(new_item));
7319
	should_fix_fields=1;
unknown's avatar
unknown committed
7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345
      }
      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 */
      }
    }
7346
    if (should_fix_fields)
unknown's avatar
af  
unknown committed
7347
      cond->update_used_tables();
7348

unknown's avatar
unknown committed
7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362
    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)
  {
    /*
7363 7364 7365 7366 7367 7368 7369
      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
7370 7371 7372 7373 7374 7375 7376 7377
    */

    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 &&
7378 7379
	  (thd->options & OPTION_AUTO_IS_NULL) &&
	  thd->insert_id())
unknown's avatar
unknown committed
7380
      {
7381
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
7382
	query_cache_abort(&thd->net);
7383
#endif
unknown's avatar
unknown committed
7384 7385 7386
	COND *new_cond;
	if ((new_cond= new Item_func_eq(args[0],
					new Item_int("last_insert_id()",
7387
						     thd->insert_id(),
unknown's avatar
unknown committed
7388 7389 7390
						     21))))
	{
	  cond=new_cond;
unknown's avatar
unknown committed
7391
	  cond->fix_fields(thd, 0, &cond);
unknown's avatar
unknown committed
7392
	}
7393
	thd->insert_id(0);		// Clear for next request
unknown's avatar
unknown committed
7394 7395 7396 7397
      }
      /* fix to replace 'NULL' dates with '0' (shreeve@uci.edu) */
      else if (((field->type() == FIELD_TYPE_DATE) ||
		(field->type() == FIELD_TYPE_DATETIME)) &&
7398 7399
		(field->flags & NOT_NULL_FLAG) &&
	       !field->table->maybe_null)
unknown's avatar
unknown committed
7400 7401 7402 7403 7404
      {
	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
7405
	  cond->fix_fields(thd, 0, &cond);
unknown's avatar
unknown committed
7406 7407 7408
	}
      }
    }
unknown's avatar
unknown committed
7409 7410 7411 7412 7413
    if (cond->const_item())
    {
      *cond_value= eval_const_cond(cond) ? Item::COND_TRUE : Item::COND_FALSE;
      return (COND*) 0;
    }
unknown's avatar
unknown committed
7414 7415 7416 7417 7418 7419 7420 7421 7422 7423
  }
  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];
7424
    if (left_item->eq(right_item,1))
unknown's avatar
unknown committed
7425 7426 7427 7428 7429 7430 7431
    {
      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;
7432
  return cond;					// Point at next and level
unknown's avatar
unknown committed
7433 7434 7435
}

/*
7436
  Return 1 if the item is a const value in all the WHERE clause
unknown's avatar
unknown committed
7437 7438 7439 7440 7441 7442 7443 7444 7445
*/

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
7446
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468
    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];
7469
    if (left_item->eq(comp_item,1))
unknown's avatar
unknown committed
7470 7471 7472 7473
    {
      if (right_item->const_item())
      {
	if (*const_item)
7474
	  return right_item->eq(*const_item, 1);
unknown's avatar
unknown committed
7475 7476 7477 7478
	*const_item=right_item;
	return 1;
      }
    }
7479
    else if (right_item->eq(comp_item,1))
unknown's avatar
unknown committed
7480 7481 7482 7483
    {
      if (left_item->const_item())
      {
	if (*const_item)
7484
	  return left_item->eq(*const_item, 1);
unknown's avatar
unknown committed
7485 7486 7487 7488 7489 7490 7491 7492 7493
	*const_item=left_item;
	return 1;
      }
    }
  }
  return 0;
}

/****************************************************************************
unknown's avatar
unknown committed
7494
  Create internal temporary table
unknown's avatar
unknown committed
7495 7496
****************************************************************************/

7497 7498 7499 7500 7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511 7512
/*
  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
    item		Item to create a field for
    table		Temporary table
    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
7513 7514
    convert_blob_length If >0 create a varstring(convert_blob_length) field 
                        instead of blob.
7515 7516 7517 7518 7519

  RETURN
    0			on error
    new_created field
*/
7520 7521 7522 7523 7524

static Field* create_tmp_field_from_field(THD *thd, Field* org_field,
                                          Item *item, TABLE *table,
                                          bool modify_item,
                                          uint convert_blob_length)
7525 7526 7527
{
  Field *new_field;

7528 7529 7530 7531 7532
  if (convert_blob_length && org_field->flags & BLOB_FLAG)
    new_field= new Field_varstring(convert_blob_length, org_field->maybe_null(),
                                   org_field->field_name, table,
                                   org_field->charset());
  else
unknown's avatar
unknown committed
7533
    new_field= org_field->new_field(thd->mem_root, table);
7534
  if (new_field)
7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564
  {
    if (modify_item)
      ((Item_field *)item)->result_field= new_field;
    else
      new_field->field_name= item->name;
    if (org_field->maybe_null())
      new_field->flags&= ~NOT_NULL_FLAG;	// Because of outer join
    if (org_field->type() == FIELD_TYPE_VAR_STRING)
      table->db_create_options|= HA_OPTION_PACK_RECORD;
  }
  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
7565 7566
    convert_blob_length If >0 create a varstring(convert_blob_length) field 
                        instead of blob.
7567 7568 7569 7570 7571

  RETURN
    0			on error
    new_created field
*/
7572 7573 7574
static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
                                         Item ***copy_func, bool modify_item,
                                         uint convert_blob_length)
7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590
{
  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:
    if (item->max_length > 255)
7591 7592 7593 7594 7595 7596 7597 7598 7599
    {
      if (convert_blob_length)
        new_field= new Field_varstring(convert_blob_length, maybe_null,
                                       item->name, table,
                                       item->collation.collation);
      else
        new_field= new Field_blob(item->max_length, maybe_null, item->name,
                                  table, item->collation.collation);
    }
7600
    else
7601 7602
      new_field= new Field_string(item->max_length, maybe_null, item->name, 
                                  table, item->collation.collation);
7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617
    break;
  case ROW_RESULT: 
  default: 
    // 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;
}

unknown's avatar
unknown committed
7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628
/*
  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
7629
    from_field          if field will be created using other field as example,
7630
                        pointer example field will be written here
unknown's avatar
unknown committed
7631 7632 7633 7634 7635 7636 7637 7638
    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
7639 7640
    convert_blob_length If >0 create a varstring(convert_blob_length) field 
                        instead of blob.
7641

unknown's avatar
unknown committed
7642 7643 7644 7645 7646
  RETURN
    0			on error
    new_created field
*/

unknown's avatar
unknown committed
7647
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
7648 7649
                        Item ***copy_func, Field **from_field,
                        bool group, bool modify_item, uint convert_blob_length)
unknown's avatar
unknown committed
7650 7651 7652 7653 7654 7655 7656 7657 7658 7659
{
  switch (type) {
  case Item::SUM_FUNC_ITEM:
  {
    Item_sum *item_sum=(Item_sum*) item;
    bool maybe_null=item_sum->maybe_null;
    switch (item_sum->sum_func()) {
    case Item_sum::AVG_FUNC:			/* Place for sum & count */
      if (group)
	return new Field_string(sizeof(double)+sizeof(longlong),
unknown's avatar
unknown committed
7660
				0, item->name,table,&my_charset_bin);
unknown's avatar
unknown committed
7661 7662 7663
      else
	return new Field_double(item_sum->max_length,maybe_null,
				item->name, table, item_sum->decimals);
unknown's avatar
af  
unknown committed
7664
    case Item_sum::VARIANCE_FUNC:		/* Place for sum & count */
7665
    case Item_sum::STD_FUNC:
unknown's avatar
unknown committed
7666 7667
      if (group)
	return	new Field_string(sizeof(double)*2+sizeof(longlong),
unknown's avatar
unknown committed
7668
				 0, item->name,table,&my_charset_bin);
unknown's avatar
unknown committed
7669 7670
      else
	return new Field_double(item_sum->max_length, maybe_null,
7671
				item->name,table,item_sum->decimals);
unknown's avatar
unknown committed
7672 7673 7674 7675 7676 7677 7678 7679 7680
    case Item_sum::UNIQUE_USERS_FUNC:
      return new Field_long(9,maybe_null,item->name,table,1);
    default:
      switch (item_sum->result_type()) {
      case REAL_RESULT:
	return new Field_double(item_sum->max_length,maybe_null,
				item->name,table,item_sum->decimals);
      case INT_RESULT:
	return new Field_longlong(item_sum->max_length,maybe_null,
7681
				  item->name,table,item->unsigned_flag);
unknown's avatar
unknown committed
7682 7683
      case STRING_RESULT:
	if (item_sum->max_length > 255)
7684 7685 7686 7687 7688 7689 7690 7691 7692
        {
          if (convert_blob_length)
            return new Field_varstring(convert_blob_length, maybe_null,
                                       item->name, table,
                                       item->collation.collation);
          else
            return new Field_blob(item_sum->max_length, maybe_null, item->name,
                                  table, item->collation.collation);
        }
unknown's avatar
unknown committed
7693
	return	new Field_string(item_sum->max_length,maybe_null,
7694
				 item->name,table,item->collation.collation);
7695
      case ROW_RESULT:
unknown's avatar
unknown committed
7696
      default:
unknown's avatar
unknown committed
7697 7698
	// This case should never be choosen
	DBUG_ASSERT(0);
unknown's avatar
af  
unknown committed
7699
	thd->fatal_error();
unknown's avatar
unknown committed
7700
	return 0;
unknown's avatar
unknown committed
7701 7702
      }
    }
unknown's avatar
af  
unknown committed
7703
    /* We never come here */
unknown's avatar
unknown committed
7704 7705
  }
  case Item::FIELD_ITEM:
7706
  case Item::DEFAULT_VALUE_ITEM:
unknown's avatar
af  
unknown committed
7707 7708
  {
    Item_field *field= (Item_field*) item;
7709 7710
    return create_tmp_field_from_field(thd, (*from_field= field->field), item,
                                       table, modify_item, convert_blob_length);
unknown's avatar
af  
unknown committed
7711
  }
unknown's avatar
unknown committed
7712 7713 7714 7715
  case Item::FUNC_ITEM:
  case Item::COND_ITEM:
  case Item::FIELD_AVG_ITEM:
  case Item::FIELD_STD_ITEM:
7716
  case Item::SUBSELECT_ITEM:
unknown's avatar
unknown committed
7717
    /* The following can only happen with 'CREATE TABLE ... SELECT' */
unknown's avatar
unknown committed
7718
  case Item::PROC_ITEM:
unknown's avatar
unknown committed
7719 7720 7721 7722
  case Item::INT_ITEM:
  case Item::REAL_ITEM:
  case Item::STRING_ITEM:
  case Item::REF_ITEM:
7723
  case Item::NULL_ITEM:
7724
  case Item::VARBIN_ITEM:
7725 7726
    return create_tmp_field_from_item(thd, item, table, copy_func, modify_item,
                                      convert_blob_length);
7727
  case Item::TYPE_HOLDER:
unknown's avatar
unknown committed
7728
  {
7729 7730
    Field *example= ((Item_type_holder *)item)->example();
    if (example)
7731 7732 7733 7734
      return create_tmp_field_from_field(thd, example, item, table, 0,
                                         convert_blob_length);
    return create_tmp_field_from_item(thd, item, table, copy_func, 0,
                                      convert_blob_length);
unknown's avatar
unknown committed
7735 7736 7737 7738 7739 7740 7741
  }
  default:					// Dosen't have to be stored
    return 0;
  }
}


unknown's avatar
unknown committed
7742 7743 7744 7745 7746 7747 7748
/*
  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
*/

unknown's avatar
unknown committed
7749 7750 7751
TABLE *
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
		 ORDER *group, bool distinct, bool save_sum_fields,
7752 7753
		 ulong select_options, ha_rows rows_limit,
		 char *table_alias)
unknown's avatar
unknown committed
7754 7755 7756
{
  TABLE *table;
  uint	i,field_count,reclength,null_count,null_pack_length,
unknown's avatar
unknown committed
7757
        hidden_null_count, hidden_null_pack_length, hidden_field_count,
unknown's avatar
unknown committed
7758 7759
	blob_count,group_null_items;
  bool	using_unique_constraint=0;
unknown's avatar
unknown committed
7760
  bool  not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS);
7761
  char	*tmpname,path[FN_REFLEN], filename[FN_REFLEN];
unknown's avatar
unknown committed
7762 7763
  byte	*pos,*group_buff;
  uchar *null_flags;
7764
  Field **reg_field, **from_field, **blob_field;
unknown's avatar
unknown committed
7765 7766 7767
  Copy_field *copy=0;
  KEY *keyinfo;
  KEY_PART_INFO *key_part_info;
unknown's avatar
unknown committed
7768
  Item **copy_func;
unknown's avatar
unknown committed
7769
  MI_COLUMNDEF *recinfo;
7770
  uint temp_pool_slot=MY_BIT_NONE;
7771

unknown's avatar
unknown committed
7772
  DBUG_ENTER("create_tmp_table");
unknown's avatar
unknown committed
7773
  DBUG_PRINT("enter",("distinct: %d  save_sum_fields: %d  rows_limit: %lu  group: %d",
unknown's avatar
unknown committed
7774
		      (int) distinct, (int) save_sum_fields,
unknown's avatar
unknown committed
7775
		      (ulong) rows_limit,test(group)));
unknown's avatar
unknown committed
7776

7777
  statistic_increment(thd->status_var.created_tmp_tables, &LOCK_status);
7778

7779
  if (use_temp_pool)
unknown's avatar
unknown committed
7780
    temp_pool_slot = bitmap_set_next(&temp_pool);
7781 7782

  if (temp_pool_slot != MY_BIT_NONE) // we got a slot
7783 7784
    sprintf(filename, "%s_%lx_%i", tmp_file_prefix,
            current_pid, temp_pool_slot);
7785
  else // if we run out of slots or we are not using tempool
7786
    sprintf(filename,"%s%lx_%lx_%x",tmp_file_prefix,current_pid,
7787
            thd->thread_id, thd->tmp_table++);
7788

unknown's avatar
af  
unknown committed
7789 7790
  if (lower_case_table_names)
    my_casedn_str(files_charset_info, path);
7791
  sprintf(path, "%s%s", mysql_tmpdir, filename);
7792

unknown's avatar
unknown committed
7793 7794 7795 7796 7797
  if (group)
  {
    if (!param->quick_group)
      group=0;					// Can't use group key
    else for (ORDER *tmp=group ; tmp ; tmp=tmp->next)
7798
    {
unknown's avatar
unknown committed
7799
      (*tmp->item)->marker=4;			// Store null in key
7800 7801 7802
      if ((*tmp->item)->max_length >= MAX_CHAR_WIDTH)
	using_unique_constraint=1;
    }
unknown's avatar
unknown committed
7803 7804
    if (param->group_length >= MAX_BLOB_WIDTH)
      using_unique_constraint=1;
unknown's avatar
unknown committed
7805 7806
    if (group)
      distinct=0;				// Can't use distinct
unknown's avatar
unknown committed
7807 7808 7809
  }

  field_count=param->field_count+param->func_count+param->sum_func_count;
unknown's avatar
unknown committed
7810
  hidden_field_count=param->hidden_field_count;
unknown's avatar
unknown committed
7811 7812
  if (!my_multi_malloc(MYF(MY_WME),
		       &table,sizeof(*table),
7813 7814 7815
		       &reg_field,  sizeof(Field*)*(field_count+1),
		       &blob_field, sizeof(Field*)*(field_count+1),
		       &from_field, sizeof(Field*)*field_count,
unknown's avatar
unknown committed
7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826
		       &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
7827
    bitmap_clear_bit(&temp_pool, temp_pool_slot);
7828
    DBUG_RETURN(NULL);				/* purecov: inspected */
unknown's avatar
unknown committed
7829 7830 7831
  }
  if (!(param->copy_field=copy=new Copy_field[field_count]))
  {
unknown's avatar
unknown committed
7832
    bitmap_clear_bit(&temp_pool, temp_pool_slot);
7833 7834
    my_free((gptr) table,MYF(0));		/* purecov: inspected */
    DBUG_RETURN(NULL);				/* purecov: inspected */
unknown's avatar
unknown committed
7835
  }
unknown's avatar
unknown committed
7836
  param->items_to_copy= copy_func;
unknown's avatar
unknown committed
7837 7838 7839 7840 7841 7842 7843
  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;
7844
  table->blob_field= (Field_blob**) blob_field;
unknown's avatar
unknown committed
7845
  table->real_name=table->path=tmpname;
7846
  table->table_name= table_alias;
unknown's avatar
unknown committed
7847 7848 7849 7850
  table->reginfo.lock_type=TL_WRITE;	/* Will be updated */
  table->db_stat=HA_OPEN_KEYFILE+HA_OPEN_RNDFILE;
  table->blob_ptr_size=mi_portable_sizeof_char_ptr;
  table->map=1;
unknown's avatar
unknown committed
7851
  table->tmp_table= TMP_TABLE;
unknown's avatar
unknown committed
7852
  table->db_low_byte_first=1;			// True for HEAP and MyISAM
7853
  table->temp_pool_slot = temp_pool_slot;
7854
  table->copy_blobs= 1;
7855
  table->in_use= thd;
unknown's avatar
unknown committed
7856
  table->table_charset= param->table_charset;
7857 7858 7859 7860 7861 7862
  table->keys_for_keyread.init();
  table->keys_in_use.init();
  table->read_only_keys.init();
  table->quick_keys.init();
  table->used_keys.init();
  table->keys_in_use_for_query.init();
unknown's avatar
unknown committed
7863

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

unknown's avatar
unknown committed
7866 7867
  reclength=blob_count=null_count=hidden_null_count=group_null_items=0;
  param->using_indirect_summary_function=0;
unknown's avatar
unknown committed
7868

unknown's avatar
unknown committed
7869
  List_iterator_fast<Item> li(fields);
unknown's avatar
unknown committed
7870 7871
  Item *item;
  Field **tmp_from_field=from_field;
7872
  while ((item=li++))
unknown's avatar
unknown committed
7873 7874
  {
    Item::Type type=item->type();
unknown's avatar
unknown committed
7875
    if (not_all_columns)
unknown's avatar
unknown committed
7876
    {
unknown's avatar
unknown committed
7877 7878 7879 7880 7881 7882 7883 7884 7885 7886
      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;
      }
7887
      if (item->const_item() && (int) hidden_field_count <= 0)
7888
        continue; // We don't have to store this
unknown's avatar
unknown committed
7889
    }
unknown's avatar
unknown committed
7890 7891 7892 7893 7894
    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++)
      {
7895 7896
	Item **argp= ((Item_sum*) item)->args + i;
	Item *arg= *argp;
unknown's avatar
unknown committed
7897 7898 7899
	if (!arg->const_item())
	{
	  Field *new_field=
7900 7901 7902
            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
7903 7904 7905 7906 7907 7908
	  if (!new_field)
	    goto err;					// Should be OOM
	  tmp_from_field++;
	  *(reg_field++)= new_field;
	  reclength+=new_field->pack_length();
	  if (new_field->flags & BLOB_FLAG)
7909 7910
	  {
	    *blob_field++= new_field;
unknown's avatar
unknown committed
7911
	    blob_count++;
7912
	  }
7913
          thd->change_item_tree(argp, new Item_field(new_field));
7914 7915 7916 7917 7918 7919 7920
	  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
            */
7921
            (*argp)->maybe_null=1;
7922
          }
unknown's avatar
unknown committed
7923 7924 7925 7926 7927
	}
      }
    }
    else
    {
unknown's avatar
unknown committed
7928 7929 7930 7931 7932 7933 7934 7935 7936 7937
      /*
	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.
      */
7938 7939 7940 7941
      Field *new_field= 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
7942 7943
      if (!new_field)
      {
7944
	if (thd->is_fatal_error)
unknown's avatar
unknown committed
7945 7946 7947 7948 7949 7950 7951 7952 7953 7954
	  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++;
      if (new_field->flags & BLOB_FLAG)
7955 7956
      {
	*blob_field++= new_field;
unknown's avatar
unknown committed
7957
	blob_count++;
7958
      }
unknown's avatar
unknown committed
7959 7960 7961 7962 7963 7964 7965
      if (item->marker == 4 && item->maybe_null)
      {
	group_null_items++;
	new_field->flags|= GROUP_FLAG;
      }
      *(reg_field++) =new_field;
    }
unknown's avatar
unknown committed
7966 7967
    if (!--hidden_field_count)
      hidden_null_count=null_count;
unknown's avatar
unknown committed
7968
  }
7969
  DBUG_ASSERT(field_count >= (uint) (reg_field - table->field));
unknown's avatar
unknown committed
7970
  field_count= (uint) (reg_field - table->field);
7971
  *blob_field= 0;				// End marker
unknown's avatar
unknown committed
7972 7973

  /* If result table is small; use a heap */
7974
  if (blob_count || using_unique_constraint ||
unknown's avatar
unknown committed
7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993
      (select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
      OPTION_BIG_TABLES)
  {
    table->file=get_new_handler(table,table->db_type=DB_TYPE_MYISAM);
    if (group &&
	(param->group_parts > table->file->max_key_parts() ||
	 param->group_length > table->file->max_key_length()))
      using_unique_constraint=1;
  }
  else
  {
    table->file=get_new_handler(table,table->db_type=DB_TYPE_HEAP);
  }

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

  table->blob_fields=blob_count;
  if (blob_count == 0)
unknown's avatar
unknown committed
7994 7995
  {
    /* We need to ensure that first byte is not 0 for the delete link */
7996
    if (param->hidden_field_count)
unknown's avatar
unknown committed
7997 7998 7999 8000 8001 8002 8003
      hidden_null_count++;
    else
      null_count++;
  }
  hidden_null_pack_length=(hidden_null_count+7)/8;
  null_pack_length=hidden_null_count+(null_count+7)/8;
  reclength+=null_pack_length;
unknown's avatar
unknown committed
8004 8005 8006 8007 8008 8009 8010 8011
  if (!reclength)
    reclength=1;				// Dummy select

  table->fields=field_count;
  table->reclength=reclength;
  {
    uint alloc_length=ALIGN_SIZE(reclength+MI_UNIQUE_HASH_LENGTH+1);
    table->rec_buff_length=alloc_length;
unknown's avatar
unknown committed
8012
    if (!(table->record[0]= (byte *) my_malloc(alloc_length*3, MYF(MY_WME))))
unknown's avatar
unknown committed
8013
      goto err;
unknown's avatar
unknown committed
8014
    table->record[1]= table->record[0]+alloc_length;
unknown's avatar
unknown committed
8015
    table->default_values= table->record[1]+alloc_length;
unknown's avatar
unknown committed
8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028
  }
  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
8029 8030 8031 8032

    table->null_flags= (uchar*) table->record[0];
    table->null_fields= null_count+ hidden_null_count;
    table->null_bytes= null_pack_length;
unknown's avatar
unknown committed
8033 8034
  }
  null_count= (blob_count == 0) ? 1 : 0;
unknown's avatar
unknown committed
8035
  hidden_field_count=param->hidden_field_count;
unknown's avatar
unknown committed
8036 8037 8038 8039 8040 8041 8042 8043 8044 8045
  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)
      {
8046 8047 8048 8049
	/*
	  We have to reserve one byte here for NULL bits,
	  as this is updated by 'end_update()'
	*/
unknown's avatar
unknown committed
8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083
	*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;
    else if (!field->zero_pack() &&
	     (field->type() == FIELD_TYPE_STRING ||
	      field->type() == FIELD_TYPE_VAR_STRING) &&
	     length >= 10 && blob_count)
unknown's avatar
unknown committed
8084
      recinfo->type=FIELD_SKIP_ENDSPACE;
unknown's avatar
unknown committed
8085 8086
    else
      recinfo->type=FIELD_NORMAL;
unknown's avatar
unknown committed
8087 8088
    if (!--hidden_field_count)
      null_count=(null_count+7) & ~7;		// move to next byte
8089 8090 8091

    // fix table name in field entry
    field->table_name= table->table_name;
unknown's avatar
unknown committed
8092 8093
  }

unknown's avatar
unknown committed
8094
  param->copy_field_end=copy;
unknown's avatar
unknown committed
8095
  param->recinfo=recinfo;
8096
  store_record(table,default_values);		// Make empty default record
unknown's avatar
unknown committed
8097

8098
  if (thd->variables.tmp_table_size == ~(ulong) 0)		// No limit
8099 8100 8101
    table->max_rows= ~(ha_rows) 0;
  else
    table->max_rows=(((table->db_type == DB_TYPE_HEAP) ?
8102 8103 8104
		      min(thd->variables.tmp_table_size,
			  thd->variables.max_heap_table_size) :
		      thd->variables.tmp_table_size)/ table->reclength);
unknown's avatar
unknown committed
8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120
  set_if_bigger(table->max_rows,1);		// For dummy start options
  keyinfo=param->keyinfo;

  if (group)
  {
    DBUG_PRINT("info",("Creating group key in temporary table"));
    table->group=group;				/* Table is grouped by key */
    param->group_buff=group_buff;
    table->keys=1;
    table->uniques= test(using_unique_constraint);
    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;
8121
    keyinfo->algorithm= HA_KEY_ALG_UNDEF;
unknown's avatar
unknown committed
8122 8123
    for (; group ; group=group->next,key_part_info++)
    {
8124
      Field *field=(*group->item)->get_tmp_table_field();
unknown's avatar
unknown committed
8125
      bool maybe_null=(*group->item)->maybe_null;
8126
      key_part_info->null_bit=0;
unknown's avatar
unknown committed
8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137
      key_part_info->field=  field;
      key_part_info->offset= field->offset();
      key_part_info->length= (uint16) field->pack_length();
      key_part_info->type=   (uint8) field->key_type();
      key_part_info->key_type =
	((ha_base_keytype) key_part_info->type == HA_KEYTYPE_TEXT ||
	 (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT) ?
	0 : FIELDFLAG_BINARY;
      if (!using_unique_constraint)
      {
	group->buff=(char*) group_buff;
unknown's avatar
unknown committed
8138
	if (!(group->field=field->new_field(thd->mem_root,table)))
unknown's avatar
unknown committed
8139 8140 8141 8142
	  goto err; /* purecov: inspected */
	if (maybe_null)
	{
	  /*
8143 8144 8145 8146
	    To be able to group on NULL, we reserve place in group_buff
	    for the NULL flag just before the column.
	    The field data is after this flag.
	    The NULL flag is updated by 'end_update()' and 'end_write()'
unknown's avatar
unknown committed
8147
	  */
8148 8149 8150 8151 8152
	  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]);
	  group->field->move_field((char*) ++group->buff);
8153
	  group_buff++;
unknown's avatar
unknown committed
8154 8155 8156 8157 8158 8159 8160 8161 8162
	}
	else
	  group->field->move_field((char*) group_buff);
	group_buff+= key_part_info->length;
      }
      keyinfo->key_length+=  key_part_info->length;
    }
  }

unknown's avatar
unknown committed
8163
  if (distinct)
unknown's avatar
unknown committed
8164
  {
unknown's avatar
unknown committed
8165 8166 8167 8168 8169 8170
    /*
      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.
    */
8171 8172
    DBUG_PRINT("info",("hidden_field_count: %d", param->hidden_field_count));

unknown's avatar
unknown committed
8173
    null_pack_length-=hidden_null_pack_length;
unknown's avatar
unknown committed
8174
    keyinfo->key_parts= ((field_count-param->hidden_field_count)+
8175
			 test(null_pack_length));
unknown's avatar
unknown committed
8176 8177
    set_if_smaller(table->max_rows, rows_limit);
    param->end_write_records= rows_limit;
unknown's avatar
unknown committed
8178 8179 8180 8181 8182 8183 8184 8185 8186 8187 8188 8189
    table->distinct=1;
    table->keys=1;
    if (blob_count)
    {
      using_unique_constraint=1;
      table->uniques=1;
    }
    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;
8190
    keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL;
unknown's avatar
unknown committed
8191 8192
    keyinfo->key_length=(uint16) reclength;
    keyinfo->name=(char*) "tmp";
8193
    keyinfo->algorithm= HA_KEY_ALG_UNDEF;
unknown's avatar
unknown committed
8194
    if (null_pack_length)
unknown's avatar
unknown committed
8195
    {
8196
      key_part_info->null_bit=0;
unknown's avatar
unknown committed
8197 8198
      key_part_info->offset=hidden_null_pack_length;
      key_part_info->length=null_pack_length;
unknown's avatar
unknown committed
8199 8200 8201 8202 8203
      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
8204
					    NullS, table, &my_charset_bin);
unknown's avatar
unknown committed
8205 8206 8207 8208
      key_part_info->key_type=FIELDFLAG_BINARY;
      key_part_info->type=    HA_KEYTYPE_BINARY;
      key_part_info++;
    }
8209
    /* Create a distinct key over the columns we are going to return */
unknown's avatar
unknown committed
8210 8211
    for (i=param->hidden_field_count, reg_field=table->field + i ;
	 i < field_count;
unknown's avatar
unknown committed
8212 8213
	 i++, reg_field++, key_part_info++)
    {
8214
      key_part_info->null_bit=0;
unknown's avatar
unknown committed
8215 8216 8217 8218 8219 8220 8221 8222 8223 8224
      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 ||
	 (ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT) ?
	0 : FIELDFLAG_BINARY;
    }
  }
8225
  if (thd->is_fatal_error)				// If end of memory
unknown's avatar
unknown committed
8226 8227 8228 8229 8230 8231 8232
    goto err;					 /* purecov: inspected */
  table->db_record_offset=1;
  if (table->db_type == DB_TYPE_MYISAM)
  {
    if (create_myisam_tmp_table(table,param,select_options))
      goto err;
  }
8233 8234
  /* Set table_name for easier debugging */
  table->table_name= base_name(tmpname);
unknown's avatar
unknown committed
8235 8236 8237 8238
  if (!open_tmp_table(table))
    DBUG_RETURN(table);

 err:
8239 8240 8241 8242 8243
  /*
    Hack to ensure that free_blobs() doesn't fail if blob_field is not yet
    complete
  */
  *table->blob_field= 0;
8244
  free_tmp_table(thd,table);                    /* purecov: inspected */
unknown's avatar
unknown committed
8245
  bitmap_clear_bit(&temp_pool, temp_pool_slot);
unknown's avatar
unknown committed
8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264
  DBUG_RETURN(NULL);				/* purecov: inspected */
}


static bool open_tmp_table(TABLE *table)
{
  int error;
  if ((error=table->file->ha_open(table->real_name,O_RDWR,HA_OPEN_TMP_TABLE)))
  {
    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,
8265
				    ulong options)
unknown's avatar
unknown committed
8266 8267 8268 8269 8270 8271 8272 8273 8274 8275
{
  int error;
  MI_KEYDEF keydef;
  MI_UNIQUEDEF uniquedef;
  KEY *keyinfo=param->keyinfo;

  DBUG_ENTER("create_myisam_tmp_table");
  if (table->keys)
  {						// Get keys for ni_create
    bool using_unique_constraint=0;
unknown's avatar
unknown committed
8276
    HA_KEYSEG *seg= (HA_KEYSEG*) sql_calloc(sizeof(*seg) *
unknown's avatar
unknown committed
8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311
					    keyinfo->key_parts);
    if (!seg)
      goto err;

    if (keyinfo->key_length >= table->file->max_key_length() ||
	keyinfo->key_parts > table->file->max_key_parts() ||
	table->uniques)
    {
      /* Can't create a key; Make a unique constraint instead of a key */
      table->keys=0;
      table->uniques=1;
      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++;
      table->reclength+=MI_UNIQUE_HASH_LENGTH;
    }
    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;
8312
      seg->flag=     0;
unknown's avatar
unknown committed
8313
      seg->language= field->charset()->number;
8314 8315
      seg->length=   keyinfo->key_part[i].length;
      seg->start=    keyinfo->key_part[i].offset;
unknown's avatar
unknown committed
8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335
      if (field->flags & BLOB_FLAG)
      {
	seg->type=
	((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
	 HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT);
	seg->bit_start=seg->length - table->blob_ptr_size;
	seg->flag= HA_BLOB_PART;
	seg->length=0;			// Whole blob in unique constraint
      }
      else
      {
	seg->type=
	  ((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
	   HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT);
	if (!(field->flags & ZEROFILL_FLAG) &&
	    (field->type() == FIELD_TYPE_STRING ||
	     field->type() == FIELD_TYPE_VAR_STRING) &&
	    keyinfo->key_part[i].length > 4)
	  seg->flag|=HA_SPACE_PACK;
      }
8336
      if (!(field->flags & NOT_NULL_FLAG))
unknown's avatar
unknown committed
8337 8338 8339
      {
	seg->null_bit= field->null_bit;
	seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]);
8340 8341 8342 8343 8344 8345 8346
	/*
	  We are using a GROUP BY on something that contains NULL
	  In this case we have to tell MyISAM that two NULL should
	  on INSERT be compared as equal
	*/
	if (!using_unique_constraint)
	  keydef.flag|= HA_NULL_ARE_EQUAL;
unknown's avatar
unknown committed
8347 8348 8349 8350 8351
      }
    }
  }
  MI_CREATE_INFO create_info;
  bzero((char*) &create_info,sizeof(create_info));
unknown's avatar
unknown committed
8352

8353 8354
  if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
      OPTION_BIG_TABLES)
unknown's avatar
unknown committed
8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367
    create_info.data_file_length= ~(ulonglong) 0;

  if ((error=mi_create(table->real_name,table->keys,&keydef,
		       (uint) (param->recinfo-param->start_recinfo),
		       param->start_recinfo,
		       table->uniques, &uniquedef,
		       &create_info,
		       HA_CREATE_TMP_TABLE)))
  {
    table->file->print_error(error,MYF(0));	/* purecov: inspected */
    table->db_stat=0;
    goto err;
  }
8368 8369
  statistic_increment(table->in_use->status_var.created_tmp_disk_tables,
		      &LOCK_status);
unknown's avatar
unknown committed
8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385
  table->db_record_offset=1;
  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");
  DBUG_PRINT("enter",("table: %s",entry->table_name));

  save_proc_info=thd->proc_info;
  thd->proc_info="removing tmp table";
8386
  free_blobs(entry);
unknown's avatar
af  
unknown committed
8387
  if (entry->file)
unknown's avatar
unknown committed
8388
  {
unknown's avatar
af  
unknown committed
8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399
    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.
    */
    if (!(test_flags & TEST_KEEP_TMP_TABLES) || entry->db_type == DB_TYPE_HEAP)
      entry->file->delete_table(entry->real_name);
unknown's avatar
unknown committed
8400 8401
    delete entry->file;
  }
unknown's avatar
af  
unknown committed
8402

unknown's avatar
unknown committed
8403 8404
  /* free blobs */
  for (Field **ptr=entry->field ; *ptr ; ptr++)
8405
    (*ptr)->free();
unknown's avatar
unknown committed
8406 8407
  my_free((gptr) entry->record[0],MYF(0));
  free_io_cache(entry);
8408

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

unknown's avatar
unknown committed
8411 8412 8413 8414 8415 8416 8417 8418 8419 8420
  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
8421 8422
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
8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442
{
  TABLE new_table;
  const char *save_proc_info;
  int write_err;
  DBUG_ENTER("create_myisam_from_heap");

  if (table->db_type != DB_TYPE_HEAP || error != HA_ERR_RECORD_FILE_FULL)
  {
    table->file->print_error(error,MYF(0));
    DBUG_RETURN(1);
  }
  new_table= *table;
  new_table.db_type=DB_TYPE_MYISAM;
  if (!(new_table.file=get_new_handler(&new_table,DB_TYPE_MYISAM)))
    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
8443
			      thd->lex->select_lex.options | thd->options))
unknown's avatar
unknown committed
8444 8445 8446
    goto err2;
  if (open_tmp_table(&new_table))
    goto err1;
unknown's avatar
af  
unknown committed
8447 8448
  if (table->file->indexes_are_disabled())
    new_table.file->disable_indexes(HA_KEY_SWITCH_ALL);
unknown's avatar
unknown committed
8449
  table->file->ha_index_or_rnd_end();
8450
  table->file->ha_rnd_init(1);
8451 8452
  if (table->no_rows)
  {
8453 8454
    new_table.file->extra(HA_EXTRA_NO_ROWS);
    new_table.no_rows=1;
8455 8456
  }

8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468
#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
8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483
  /* 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
8484
  (void) table->file->ha_rnd_end();
unknown's avatar
unknown committed
8485 8486 8487 8488 8489 8490
  (void) table->file->close();
  (void) table->file->delete_table(table->real_name);
  delete table->file;
  table->file=0;
  *table =new_table;
  table->file->change_table_ptr(table);
8491 8492
  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
8493 8494 8495 8496 8497
  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
8498
  (void) table->file->ha_rnd_end();
unknown's avatar
unknown committed
8499 8500 8501 8502 8503 8504 8505 8506 8507 8508
  (void) new_table.file->close();
 err1:
  new_table.file->delete_table(new_table.real_name);
  delete new_table.file;
 err2:
  thd->proc_info=save_proc_info;
  DBUG_RETURN(1);
}


8509 8510 8511 8512 8513 8514
/****************************************************************************
  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
****************************************************************************/
unknown's avatar
unknown committed
8515 8516 8517 8518

static int
do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
{
8519
  int error= 0;
unknown's avatar
unknown committed
8520
  JOIN_TAB *join_tab;
8521
  Next_select_func end_select;
unknown's avatar
unknown committed
8522 8523 8524 8525
  DBUG_ENTER("do_select");

  join->procedure=procedure;
  /*
8526
    Tell the client how many fields there are in a row
unknown's avatar
unknown committed
8527 8528
  */
  if (!table)
8529 8530
    join->result->send_fields(*fields,
                              Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
unknown's avatar
unknown committed
8531 8532 8533 8534 8535
  else
  {
    VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
    empty_record(table);
  }
unknown's avatar
unknown committed
8536
  join->tmp_table= table;			/* Save for easy recursion */
unknown's avatar
unknown committed
8537 8538 8539 8540 8541 8542 8543 8544 8545
  join->fields= fields;

  /* Set up select_end */
  if (table)
  {
    if (table->group && join->tmp_table_param.sum_func_count)
    {
      if (table->keys)
      {
8546
	DBUG_PRINT("info",("Using end_update"));
unknown's avatar
unknown committed
8547
	end_select=end_update;
unknown's avatar
unknown committed
8548 8549
        if (!table->file->inited)
          table->file->ha_index_init(0);
unknown's avatar
unknown committed
8550 8551
      }
      else
8552 8553
      {
	DBUG_PRINT("info",("Using end_unique_update"));
unknown's avatar
unknown committed
8554
	end_select=end_unique_update;
8555
      }
unknown's avatar
unknown committed
8556 8557 8558 8559 8560 8561 8562 8563 8564 8565 8566 8567 8568 8569
    }
    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
  {
8570 8571 8572 8573 8574 8575 8576 8577 8578 8579
    /* 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
8580
    else
8581
      end_select= end_send;
unknown's avatar
unknown committed
8582 8583 8584 8585 8586 8587 8588
  }
  join->join_tab[join->tables-1].next_select=end_select;

  join_tab=join->join_tab+join->const_tables;
  join->send_records=0;
  if (join->tables == join->const_tables)
  {
8589
    /*
8590
      HAVING will be checked after processing aggregate functions,
8591 8592
      But WHERE should checkd here (we alredy have read tables)
    */
unknown's avatar
unknown committed
8593
    if (!join->conds || join->conds->val_int())
unknown's avatar
unknown committed
8594
    {
8595 8596
      if (!(error=(*end_select)(join,join_tab,0)) || error == -3)
	error=(*end_select)(join,join_tab,1);
unknown's avatar
unknown committed
8597
    }
unknown's avatar
af  
unknown committed
8598 8599
    else if (join->send_row_on_empty_set())
      error= join->result->send_data(*join->fields);
unknown's avatar
unknown committed
8600 8601 8602
  }
  else
  {
unknown's avatar
unknown committed
8603
    error= sub_select(join,join_tab,0);
unknown's avatar
unknown committed
8604
    if (error >= 0)
unknown's avatar
unknown committed
8605
      error= sub_select(join,join_tab,1);
unknown's avatar
unknown committed
8606
    if (error == -3)
unknown's avatar
unknown committed
8607
      error= 0;					/* select_limit used */
unknown's avatar
unknown committed
8608
  }
8609

unknown's avatar
unknown committed
8610
  if (error >= 0)
unknown's avatar
unknown committed
8611
  {
8612 8613
    error=0;
    if (!table)					// If sending data to client
8614
    {
8615
      /*
8616 8617
	The following will unlock all cursors if the command wasn't an
	update command
8618
      */
8619
      join->join_free(0);				// Unlock all cursors
8620
      if (join->result->send_eof())
8621
	error= 1;				// Don't send error
8622
    }
unknown's avatar
unknown committed
8623 8624 8625 8626
    DBUG_PRINT("info",("%ld records output",join->send_records));
  }
  if (table)
  {
8627
    int tmp;
unknown's avatar
unknown committed
8628 8629
    if ((tmp=table->file->extra(HA_EXTRA_NO_CACHE)))
    {
8630 8631
      DBUG_PRINT("error",("extra(HA_EXTRA_NO_CACHE) failed"));
      my_errno= tmp;
unknown's avatar
unknown committed
8632 8633
      error= -1;
    }
unknown's avatar
unknown committed
8634
    if ((tmp=table->file->ha_index_or_rnd_end()))
unknown's avatar
unknown committed
8635
    {
unknown's avatar
unknown committed
8636
      DBUG_PRINT("error",("ha_index_or_rnd_end() failed"));
8637
      my_errno= tmp;
unknown's avatar
unknown committed
8638 8639
      error= -1;
    }
8640
    if (error == -1)
unknown's avatar
unknown committed
8641 8642
      table->file->print_error(my_errno,MYF(0));
  }
8643 8644 8645 8646 8647 8648
#ifndef DBUG_OFF
  if (error)
  {
    DBUG_PRINT("error",("Error: do_select() failed"));
  }
#endif
unknown's avatar
unknown committed
8649
  DBUG_RETURN(join->thd->net.report_error ? -1 : error);
unknown's avatar
unknown committed
8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663
}


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);
  }
8664 8665
  if (join->thd->killed)		// If aborted by user
  {
unknown's avatar
SCRUM  
unknown committed
8666
    join->thd->send_kill_message();
8667 8668
    return -2;				 /* purecov: inspected */
  }
unknown's avatar
unknown committed
8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679
  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 */
}

8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705 8706 8707 8708 8709 8710 8711 8712 8713 8714 8715 8716 8717 8718 8719 8720 8721 8722 8723 8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783
/*
  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
8784 8785 8786 8787
  STRUCTURE NOTES
    join_tab->first_unmatched points always backwards to the first inner
    table of the embedding nested join, if any.

8788 8789 8790 8791
  RETURN
    0, if success
    # of the error, otherwise
*/
unknown's avatar
unknown committed
8792 8793 8794 8795 8796 8797 8798 8799 8800

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;
8801 8802 8803 8804 8805 8806 8807
  JOIN_TAB *first_unmatched;
  JOIN_TAB *tab;
  bool found= 0;
  /* Cache variables for faster loop */
  COND *select_cond= join_tab->select_cond;
  JOIN_TAB *first_inner_tab= join_tab->first_inner;
   
8808
  my_bool *report_error= &(join->thd->net.report_error);
unknown's avatar
unknown committed
8809
  join->return_tab= join_tab;
unknown's avatar
unknown committed
8810

8811
  if (join_tab->last_inner)
unknown's avatar
unknown committed
8812 8813
  {
    /* join_tab is the first inner table for an outer join operation. */
8814 8815 8816 8817 8818 8819 8820 8821 8822

    /* 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
8823 8824
  if (!(error=(*join_tab->read_first_record)(join_tab)))
  {
unknown's avatar
unknown committed
8825 8826 8827
    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
8828 8829
    READ_RECORD *info= &join_tab->read_record;

8830
    join->thd->row_count= 0;
unknown's avatar
unknown committed
8831 8832 8833 8834
    do
    {
      if (join->thd->killed)			// Aborted by user
      {
unknown's avatar
SCRUM  
unknown committed
8835
	join->thd->send_kill_message();
unknown's avatar
unknown committed
8836 8837
	return -2;				/* purecov: inspected */
      }
8838
      DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
8839
      if (!select_cond || select_cond->val_int())
unknown's avatar
unknown committed
8840
      {
8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906
        /* 
          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
8907
	    return error;
unknown's avatar
unknown committed
8908
          if (join->return_tab < join_tab)
8909
              return 0;
unknown's avatar
unknown committed
8910 8911 8912 8913 8914
	  /*
	    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
8915 8916
	  if (not_used_in_distinct && found_records != join->found_records)
	    return 0;
unknown's avatar
unknown committed
8917
	}
unknown's avatar
unknown committed
8918
	else
8919 8920 8921 8922 8923 8924 8925 8926 8927 8928
	  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
8929
      }
unknown's avatar
af  
unknown committed
8930

8931
    } while (!(error=info->read_record(info)) && !(*report_error));
unknown's avatar
unknown committed
8932
  }
8933
  if (error > 0 || (*report_error))				// Fatal error
unknown's avatar
unknown committed
8934 8935
    return -1;

8936 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 8970 8971 8972 8973 8974 8975 8976
  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 */
      restore_record(join_tab->table,default_values);  // Make empty record
      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
8977
	  join->return_tab= tab;
8978 8979 8980
          return 0;
        }
      }
unknown's avatar
unknown committed
8981
    }
8982 8983 8984 8985 8986 8987 8988 8989
    /*
      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
8990 8991 8992 8993 8994 8995
  }
  return 0;
}


static int
unknown's avatar
af  
unknown committed
8996
flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
unknown's avatar
unknown committed
8997 8998 8999 9000 9001 9002
{
  int error;
  READ_RECORD *info;

  if (!join_tab->cache.records)
    return 0;				/* Nothing to do */
unknown's avatar
af  
unknown committed
9003
  if (skip_last)
unknown's avatar
unknown committed
9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015
    (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)))
  {
9016
    reset_cache_write(&join_tab->cache);
unknown's avatar
unknown committed
9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030
    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
9031
      join->thd->send_kill_message();
unknown's avatar
unknown committed
9032 9033 9034 9035
      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
9036
		   !join_tab->cache.select->skip_record()))
unknown's avatar
unknown committed
9037 9038
    {
      uint i;
9039
      reset_cache_read(&join_tab->cache);
unknown's avatar
af  
unknown committed
9040
      for (i=(join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;)
unknown's avatar
unknown committed
9041 9042
      {
	read_cached_record(join_tab);
unknown's avatar
af  
unknown committed
9043
	if (!select || !select->skip_record())
unknown's avatar
unknown committed
9044
	  if ((error=(join_tab->next_select)(join,join_tab+1,0)) < 0)
9045 9046
          {
            reset_cache_write(&join_tab->cache);
unknown's avatar
unknown committed
9047
	    return error; /* purecov: inspected */
9048
          }
unknown's avatar
unknown committed
9049 9050 9051 9052
      }
    }
  } while (!(error=info->read_record(info)));

unknown's avatar
af  
unknown committed
9053
  if (skip_last)
unknown's avatar
unknown committed
9054
    read_cached_record(join_tab);		// Restore current record
9055
  reset_cache_write(&join_tab->cache);
unknown's avatar
unknown committed
9056 9057 9058 9059 9060 9061 9062 9063 9064
  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;
}


/*****************************************************************************
9065 9066
  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
9067
*****************************************************************************/
9068 9069 9070

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

9071
int report_error(TABLE *table, int error)
9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089
{
  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'",
		    error, table->path);
  table->file->print_error(error,MYF(0));
  return 1;
}


9090
int safe_index_read(JOIN_TAB *tab)
9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101
{
  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
9102
static int
9103
join_read_const_table(JOIN_TAB *tab, POSITION *pos)
unknown's avatar
unknown committed
9104 9105
{
  int error;
9106 9107 9108 9109 9110 9111 9112
  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
9113
  {
9114 9115 9116 9117 9118 9119 9120
    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;
      if (!table->outer_join || error > 0)
	DBUG_RETURN(error);
unknown's avatar
unknown committed
9121
    }
9122 9123 9124
  }
  else
  {
unknown's avatar
af  
unknown committed
9125
    if (!table->key_read && table->used_keys.is_set(tab->ref.key) &&
9126 9127
	!table->no_keyread &&
        (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY)
unknown's avatar
af  
unknown committed
9128 9129 9130
    {
      table->key_read=1;
      table->file->extra(HA_EXTRA_KEYREAD);
unknown's avatar
unknown committed
9131
      tab->index= tab->ref.key;
unknown's avatar
af  
unknown committed
9132
    }
9133
    if ((error=join_read_const(tab)))
unknown's avatar
unknown committed
9134
    {
9135 9136 9137 9138 9139
      tab->info="unique row not found";
      /* Mark for EXPLAIN that the row was not found */
      pos->records_read=0.0;
      if (!table->outer_join || error > 0)
	DBUG_RETURN(error);
unknown's avatar
unknown committed
9140
    }
unknown's avatar
unknown committed
9141 9142 9143 9144 9145
    if (table->key_read)
    {
      table->key_read=0;
      table->file->extra(HA_EXTRA_NO_KEYREAD);
    }
unknown's avatar
unknown committed
9146
  }
unknown's avatar
unknown committed
9147
  if (*tab->on_expr_ref && !table->null_row)
9148
  {
unknown's avatar
unknown committed
9149
    if ((table->null_row= test((*tab->on_expr_ref)->val_int() == 0)))
unknown's avatar
af  
unknown committed
9150 9151
      mark_as_null_row(table);  
  }
9152 9153
  if (!table->null_row)
    table->maybe_null=0;
unknown's avatar
unknown committed
9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164
  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
  {
9165 9166
    if ((error=table->file->read_first_row(table->record[0],
					   table->primary_key)))
unknown's avatar
unknown committed
9167 9168
    {
      if (error != HA_ERR_END_OF_FILE)
9169
	return report_error(table, error);
unknown's avatar
unknown committed
9170 9171 9172 9173
      table->null_row=1;			// This is ok.
      empty_record(table);			// Make empty record
      return -1;
    }
unknown's avatar
unknown committed
9174
    store_record(table,record[1]);
unknown's avatar
unknown committed
9175 9176
  }
  else if (!table->status)			// Only happens with left join
unknown's avatar
unknown committed
9177
    restore_record(table,record[1]);			// restore old record
unknown's avatar
unknown committed
9178 9179 9180 9181 9182
  table->null_row=0;
  return table->status ? -1 : 0;
}


9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195
/*
  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
9196 9197 9198 9199 9200 9201 9202
static int
join_read_const(JOIN_TAB *tab)
{
  int error;
  TABLE *table= tab->table;
  if (table->status & STATUS_GARBAGE)		// If first read
  {
9203
    table->status= 0;
unknown's avatar
unknown committed
9204 9205 9206 9207 9208 9209 9210 9211 9212 9213
    if (cp_buffer_from_ref(&tab->ref))
      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)
    {
9214
      table->status= STATUS_NOT_FOUND;
unknown's avatar
unknown committed
9215 9216 9217
      table->null_row=1;
      empty_record(table);
      if (error != HA_ERR_KEY_NOT_FOUND)
9218
	return report_error(table, error);
unknown's avatar
unknown committed
9219 9220
      return -1;
    }
unknown's avatar
unknown committed
9221
    store_record(table,record[1]);
unknown's avatar
unknown committed
9222
  }
unknown's avatar
unknown committed
9223 9224 9225
  else if (!(table->status & ~STATUS_NULL_ROW))	// Only happens with left join
  {
    table->status=0;
unknown's avatar
unknown committed
9226
    restore_record(table,record[1]);			// restore old record
unknown's avatar
unknown committed
9227
  }
unknown's avatar
unknown committed
9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238
  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
9239 9240
  if (!table->file->inited)
    table->file->ha_index_init(tab->ref.key);
unknown's avatar
unknown committed
9241
  if (cmp_buffer_with_ref(tab) ||
9242
      (table->status & (STATUS_GARBAGE | STATUS_NO_PARENT | STATUS_NULL_ROW)))
unknown's avatar
unknown committed
9243 9244 9245 9246 9247 9248 9249 9250 9251 9252
  {
    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)
9253
      return report_error(table, error);
unknown's avatar
unknown committed
9254
  }
9255
  table->null_row=0;
unknown's avatar
unknown committed
9256 9257 9258 9259 9260 9261 9262 9263 9264 9265
  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
9266 9267
  if (!table->file->inited)
    table->file->ha_index_init(tab->ref.key);
unknown's avatar
unknown committed
9268 9269 9270 9271 9272 9273 9274
  if (cp_buffer_from_ref(&tab->ref))
    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)
9275
      return report_error(table, error);
unknown's avatar
unknown committed
9276 9277 9278 9279 9280
    return -1; /* purecov: inspected */
  }
  return 0;
}

9281

9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292
/*
  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
9293 9294
  if (!table->file->inited)
    table->file->ha_index_init(tab->ref.key);
9295 9296 9297 9298 9299 9300 9301
  if (cp_buffer_from_ref(&tab->ref))
    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)
9302
      return report_error(table, error);
9303 9304 9305 9306 9307
    return -1; /* purecov: inspected */
  }
  return 0;
}

unknown's avatar
unknown committed
9308 9309 9310 9311 9312 9313 9314 9315 9316 9317

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


static int
9318
join_read_next_same(READ_RECORD *info)
unknown's avatar
unknown committed
9319 9320 9321 9322 9323 9324 9325 9326 9327 9328
{
  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)
9329
      return report_error(table, error);
unknown's avatar
unknown committed
9330 9331 9332 9333 9334 9335
    table->status= STATUS_GARBAGE;
    return -1;
  }
  return 0;
}

9336

9337 9338 9339 9340 9341 9342 9343 9344
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])))
9345
    return report_error(table, error);
unknown's avatar
af  
unknown committed
9346 9347
  if (key_cmp_if_same(table, tab->ref.key_buff, tab->ref.key,
                      tab->ref.key_length))
9348 9349
  {
    table->status=STATUS_NOT_FOUND;
9350
    error= -1;
9351 9352 9353 9354
  }
  return error;
}

unknown's avatar
unknown committed
9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369

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;
9370 9371
  return tab->select->test_quick_select(tab->join->thd, tab->keys,
					(table_map) 0, HA_POS_ERROR);
unknown's avatar
unknown committed
9372 9373 9374 9375 9376 9377
}


static int
join_init_read_record(JOIN_TAB *tab)
{
9378 9379
  if (tab->select && tab->select->quick && tab->select->quick->reset())
    return 1;
9380 9381
  init_read_record(&tab->read_record, tab->join->thd, tab->table,
		   tab->select,1,1);
unknown's avatar
unknown committed
9382 9383 9384
  return (*tab->read_record.read_record)(&tab->read_record);
}

9385

unknown's avatar
unknown committed
9386
static int
9387
join_read_first(JOIN_TAB *tab)
unknown's avatar
unknown committed
9388 9389 9390
{
  int error;
  TABLE *table=tab->table;
9391
  if (!table->key_read && table->used_keys.is_set(tab->index) &&
unknown's avatar
unknown committed
9392
      !table->no_keyread)
unknown's avatar
unknown committed
9393 9394 9395 9396 9397
  {
    table->key_read=1;
    table->file->extra(HA_EXTRA_KEYREAD);
  }
  tab->table->status=0;
9398
  tab->read_record.read_record=join_read_next;
unknown's avatar
unknown committed
9399 9400 9401 9402
  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
9403 9404
  if (!table->file->inited)
    table->file->ha_index_init(tab->index);
9405
  if ((error=tab->table->file->index_first(tab->table->record[0])))
unknown's avatar
unknown committed
9406 9407
  {
    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
9408
      report_error(table, error);
unknown's avatar
unknown committed
9409 9410 9411 9412 9413
    return -1;
  }
  return 0;
}

9414

unknown's avatar
unknown committed
9415
static int
9416
join_read_next(READ_RECORD *info)
unknown's avatar
unknown committed
9417
{
9418 9419 9420
  int error;
  if ((error=info->file->index_next(info->record)))
    return report_error(info->table, error);
unknown's avatar
unknown committed
9421 9422 9423
  return 0;
}

9424

unknown's avatar
unknown committed
9425
static int
9426
join_read_last(JOIN_TAB *tab)
unknown's avatar
unknown committed
9427 9428 9429
{
  TABLE *table=tab->table;
  int error;
9430
  if (!table->key_read && table->used_keys.is_set(tab->index) &&
9431
      !table->no_keyread)
unknown's avatar
unknown committed
9432 9433 9434 9435 9436
  {
    table->key_read=1;
    table->file->extra(HA_EXTRA_KEYREAD);
  }
  tab->table->status=0;
9437
  tab->read_record.read_record=join_read_prev;
unknown's avatar
unknown committed
9438 9439 9440 9441
  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
9442 9443
  if (!table->file->inited)
    table->file->ha_index_init(tab->index);
9444 9445
  if ((error= tab->table->file->index_last(tab->table->record[0])))
    return report_error(table, error);
unknown's avatar
unknown committed
9446 9447 9448
  return 0;
}

9449

unknown's avatar
unknown committed
9450
static int
9451
join_read_prev(READ_RECORD *info)
unknown's avatar
unknown committed
9452
{
9453 9454 9455
  int error;
  if ((error= info->file->index_prev(info->record)))
    return report_error(info->table, error);
unknown's avatar
unknown committed
9456 9457 9458
  return 0;
}

9459

unknown's avatar
unknown committed
9460 9461 9462 9463 9464 9465
static int
join_ft_read_first(JOIN_TAB *tab)
{
  int error;
  TABLE *table= tab->table;

unknown's avatar
unknown committed
9466 9467
  if (!table->file->inited)
    table->file->ha_index_init(tab->ref.key);
unknown's avatar
unknown committed
9468
#if NOT_USED_YET
unknown's avatar
unknown committed
9469
  if (cp_buffer_from_ref(&tab->ref))       // as ft-key doesn't use store_key's
unknown's avatar
unknown committed
9470
    return -1;                             // see also FT_SELECT::init()
unknown's avatar
unknown committed
9471
#endif
9472
  table->file->ft_init();
unknown's avatar
unknown committed
9473

9474 9475
  if ((error= table->file->ft_read(table->record[0])))
    return report_error(table, error);
unknown's avatar
unknown committed
9476 9477 9478 9479 9480 9481
  return 0;
}

static int
join_ft_read_next(READ_RECORD *info)
{
9482 9483 9484
  int error;
  if ((error= info->file->ft_read(info->table->record[0])))
    return report_error(info->table, error);
unknown's avatar
unknown committed
9485 9486 9487 9488
  return 0;
}


9489 9490 9491 9492 9493 9494 9495 9496 9497 9498
/*
  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
9499
  *tab->ref.null_ref_key= 0;			// Clear null byte
9500 9501 9502 9503
  if ((res= join_read_always_key(tab)) >= 0)
    return res;

  /* Then read key with null value */
unknown's avatar
af  
unknown committed
9504
  *tab->ref.null_ref_key= 1;			// Set null byte
9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517
  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
9518
  if (*tab->ref.null_ref_key)
9519
    return -1;					// All keys read
unknown's avatar
af  
unknown committed
9520 9521
  *tab->ref.null_ref_key= 1;			// Set null byte
  return safe_index_read(tab);			// then read null keys
9522 9523 9524
}


unknown's avatar
unknown committed
9525
/*****************************************************************************
9526 9527 9528
  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
9529 9530
*****************************************************************************/

9531
/* ARGSUSED */
unknown's avatar
unknown committed
9532 9533 9534 9535 9536 9537 9538 9539
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;
9540
    if (join->having && join->having->val_int() == 0)
unknown's avatar
unknown committed
9541
      DBUG_RETURN(0);				// Didn't match having
9542
    error=0;
unknown's avatar
unknown committed
9543 9544
    if (join->procedure)
      error=join->procedure->send_row(*join->fields);
unknown's avatar
unknown committed
9545
    else if (join->do_send_rows)
unknown's avatar
unknown committed
9546 9547 9548
      error=join->result->send_data(*join->fields);
    if (error)
      DBUG_RETURN(-1); /* purecov: inspected */
9549
    if (++join->send_records >= join->unit->select_limit_cnt &&
unknown's avatar
unknown committed
9550
	join->do_send_rows)
9551 9552 9553
    {
      if (join->select_options & OPTION_FOUND_ROWS)
      {
9554
	JOIN_TAB *jt=join->join_tab;
9555
	if ((join->tables == 1) && !join->tmp_table && !join->sort_and_group
9556
	    && !join->send_group_parts && !join->having && !jt->select_cond &&
9557
	    !(jt->select && jt->select->quick) &&
unknown's avatar
unknown committed
9558 9559
	    !(jt->table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
            (jt->ref.key < 0))
9560
	{
9561
	  /* Join over all rows in table;  Return number of found rows */
9562 9563
	  TABLE *table=jt->table;

9564
	  join->select_options ^= OPTION_FOUND_ROWS;
unknown's avatar
unknown committed
9565 9566
	  if (table->sort.record_pointers ||
	      (table->sort.io_cache && my_b_inited(table->sort.io_cache)))
9567 9568
	  {
	    /* Using filesort */
unknown's avatar
unknown committed
9569
	    join->send_records= table->sort.found_records;
9570 9571 9572 9573 9574 9575
	  }
	  else
	  {
	    table->file->info(HA_STATUS_VARIABLE);
	    join->send_records = table->file->records;
	  }
9576 9577 9578
	}
	else 
	{
9579
	  join->do_send_rows= 0;
unknown's avatar
unknown committed
9580 9581
	  if (join->unit->fake_select_lex)
	    join->unit->fake_select_lex->select_limit= HA_POS_ERROR;
9582 9583
	  DBUG_RETURN(0);
	}
9584
      }
unknown's avatar
unknown committed
9585
      DBUG_RETURN(-3);				// Abort nicely
9586
    }
9587 9588 9589 9590 9591 9592 9593 9594
    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
9595 9596 9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612 9613 9614 9615 9616 9617 9618 9619 9620 9621
  }
  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)
      {
9622
	int error=0;
unknown's avatar
unknown committed
9623 9624
	if (join->procedure)
	{
9625
	  if (join->having && join->having->val_int() == 0)
unknown's avatar
unknown committed
9626
	    error= -1;				// Didn't satisfy having
9627 9628 9629 9630 9631 9632
 	  else
	  {
	    if (join->do_send_rows)
	      error=join->procedure->send_row(*join->fields) ? 1 : 0;
	    join->send_records++;
	  }
unknown's avatar
unknown committed
9633 9634 9635 9636 9637 9638
	  if (end_of_records && join->procedure->end_of_records())
	    error= 1;				// Fatal error
	}
	else
	{
	  if (!join->first_record)
9639 9640
	  {
	    /* No matching rows for group function */
9641
	    join->clear();
9642
	  }
9643
	  if (join->having && join->having->val_int() == 0)
unknown's avatar
unknown committed
9644
	    error= -1;				// Didn't satisfy having
9645 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655
	  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
9656 9657 9658
	}
	if (error > 0)
	  DBUG_RETURN(-1);			/* purecov: inspected */
9659 9660
	if (end_of_records)
	  DBUG_RETURN(0);
9661
	if (join->send_records >= join->unit->select_limit_cnt &&
9662 9663 9664 9665 9666
	    join->do_send_rows)
	{
	  if (!(join->select_options & OPTION_FOUND_ROWS))
	    DBUG_RETURN(-3);				// Abort nicely
	  join->do_send_rows=0;
9667
	  join->unit->select_limit_cnt = HA_POS_ERROR;
9668
        }
9669 9670 9671 9672 9673 9674 9675 9676
        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
9677 9678 9679 9680 9681 9682 9683 9684 9685 9686 9687 9688
      }
    }
    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);
9689 9690
      if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
	DBUG_RETURN(-1);
unknown's avatar
unknown committed
9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703 9704 9705 9706 9707 9708 9709 9710 9711 9712 9713 9714
      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
9715
    join->thd->send_kill_message();
unknown's avatar
unknown committed
9716 9717 9718 9719 9720
    DBUG_RETURN(-2);				/* purecov: inspected */
  }
  if (!end_of_records)
  {
    copy_fields(&join->tmp_table_param);
unknown's avatar
unknown committed
9721
    copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
9722

9723
#ifdef TO_BE_DELETED
unknown's avatar
unknown committed
9724 9725 9726 9727 9728 9729 9730 9731 9732
    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)
	{
9733
	  Field *field=item->get_tmp_table_field();
9734
	  field->ptr[-1]= (byte) (field->is_null() ? 1 : 0);
unknown's avatar
unknown committed
9735 9736 9737
	}
      }
    }
9738
#endif
unknown's avatar
unknown committed
9739 9740
    if (!join->having || join->having->val_int())
    {
unknown's avatar
unknown committed
9741
      join->found_records++;
unknown's avatar
unknown committed
9742 9743
      if ((error=table->file->write_row(table->record[0])))
      {
unknown's avatar
unknown committed
9744 9745 9746
	if (error == HA_ERR_FOUND_DUPP_KEY ||
	    error == HA_ERR_FOUND_DUPP_UNIQUE)
	  goto end;
unknown's avatar
unknown committed
9747 9748
	if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
				    error,1))
9749
	  DBUG_RETURN(-1);			// Not a table_is_full error
unknown's avatar
unknown committed
9750
	table->uniques=0;			// To ensure rows are the same
9751
      }
unknown's avatar
unknown committed
9752
      if (++join->send_records >= join->tmp_table_param.end_write_records &&
9753 9754 9755 9756 9757
	  join->do_send_rows)
      {
	if (!(join->select_options & OPTION_FOUND_ROWS))
	  DBUG_RETURN(-3);
	join->do_send_rows=0;
9758
	join->unit->select_limit_cnt = HA_POS_ERROR;
9759
	DBUG_RETURN(0);
unknown's avatar
unknown committed
9760 9761 9762
      }
    }
  }
unknown's avatar
unknown committed
9763
end:
unknown's avatar
unknown committed
9764 9765 9766 9767 9768 9769 9770 9771 9772 9773 9774 9775 9776 9777 9778 9779 9780 9781 9782
  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
9783
    join->thd->send_kill_message();
unknown's avatar
unknown committed
9784 9785 9786
    DBUG_RETURN(-2);				/* purecov: inspected */
  }

unknown's avatar
unknown committed
9787
  join->found_records++;
unknown's avatar
unknown committed
9788 9789 9790 9791 9792 9793
  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);
9794
    /* Store in the used key if the field was 0 */
unknown's avatar
unknown committed
9795
    if (item->maybe_null)
9796
      group->buff[-1]=item->null_value ? 1 : 0;
unknown's avatar
unknown committed
9797 9798 9799 9800 9801
  }
  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
9802
    restore_record(table,record[1]);
unknown's avatar
unknown committed
9803 9804 9805 9806 9807 9808 9809 9810 9811 9812 9813 9814 9815 9816 9817 9818 9819 9820
    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);
  }

  /* The null bits are already set */
  KEY_PART_INFO *key_part;
  for (group=table->group,key_part=table->key_info[0].key_part;
       group ;
       group=group->next,key_part++)
    memcpy(table->record[0]+key_part->offset, group->buff, key_part->length);

  init_tmptable_sum_functions(join->sum_funcs);
unknown's avatar
unknown committed
9821
  copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
9822 9823
  if ((error=table->file->write_row(table->record[0])))
  {
unknown's avatar
unknown committed
9824 9825
    if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
				error, 0))
unknown's avatar
unknown committed
9826 9827
      DBUG_RETURN(-1);				// Not a table_is_full error
    /* Change method to update rows */
unknown's avatar
unknown committed
9828
    table->file->ha_index_init(0);
unknown's avatar
unknown committed
9829 9830 9831 9832 9833 9834 9835 9836 9837 9838 9839 9840 9841 9842 9843 9844 9845 9846 9847 9848
    join->join_tab[join->tables-1].next_select=end_unique_update;
  }
  join->send_records++;
  DBUG_RETURN(0);
}

/* 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
9849
    join->thd->send_kill_message();
unknown's avatar
unknown committed
9850 9851 9852 9853 9854
    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
9855
  copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
9856 9857 9858 9859 9860 9861 9862 9863 9864 9865 9866 9867 9868 9869 9870

  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
9871
    restore_record(table,record[1]);
unknown's avatar
unknown committed
9872 9873 9874 9875 9876 9877 9878 9879 9880 9881 9882 9883 9884 9885 9886 9887 9888 9889 9890 9891 9892 9893 9894 9895
    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
9896
    join->thd->send_kill_message();
unknown's avatar
unknown committed
9897 9898 9899 9900 9901 9902 9903 9904 9905 9906 9907 9908
    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();
      if (idx < (int) join->send_group_parts)
      {
	if (!join->first_record)
9909 9910
	{
	  /* No matching rows for group function */
9911
	  join->clear();
9912
	}
unknown's avatar
unknown committed
9913 9914 9915 9916 9917
	copy_sum_funcs(join->sum_funcs);
	if (!join->having || join->having->val_int())
	{
	  if ((error=table->file->write_row(table->record[0])))
	  {
unknown's avatar
unknown committed
9918
	    if (create_myisam_from_heap(join->thd, table,
unknown's avatar
unknown committed
9919
					&join->tmp_table_param,
unknown's avatar
unknown committed
9920
					error, 0))
9921
	      DBUG_RETURN(-1);			// Not a table_is_full error
unknown's avatar
unknown committed
9922 9923 9924 9925 9926 9927 9928 9929 9930 9931
	  }
	  else
	    join->send_records++;
	}
	if (end_of_records)
	  DBUG_RETURN(0);
      }
    }
    else
    {
9932 9933
      if (end_of_records)
	DBUG_RETURN(0);
unknown's avatar
unknown committed
9934 9935 9936 9937 9938 9939
      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
9940
      copy_funcs(join->tmp_table_param.items_to_copy);
9941 9942
      if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
	DBUG_RETURN(-1);
unknown's avatar
unknown committed
9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9954 9955 9956
      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);
}


/*****************************************************************************
9957 9958 9959 9960 9961
  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
9962 9963 9964 9965 9966 9967 9968
*****************************************************************************/

/* 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;
9969 9970
  // 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
9971 9972
  {
    Item *ref_item=part_of_refkey(field->table,field);
9973
    if (ref_item && ref_item->eq(right_item,1))
unknown's avatar
unknown committed
9974 9975
    {
      if (right_item->type() == Item::FIELD_ITEM)
9976 9977
	return (field->eq_def(((Item_field *) right_item)->field));
      if (right_item->const_item() && !(right_item->is_null()))
unknown's avatar
unknown committed
9978
      {
9979 9980 9981
	/*
	  We can remove binary fields and numerical fields except float,
	  as float comparison isn't 100 % secure
unknown's avatar
af  
unknown committed
9982
	  We have to keep binary strings to be able to check for end spaces
9983
	*/
unknown's avatar
unknown committed
9984
	if (field->binary() &&
unknown's avatar
af  
unknown committed
9985 9986
	    field->real_type() != FIELD_TYPE_STRING &&
	    field->real_type() != FIELD_TYPE_VAR_STRING &&
unknown's avatar
unknown committed
9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998
	    (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
9999
make_cond_for_table(COND *cond, table_map tables, table_map used_table)
unknown's avatar
unknown committed
10000 10001 10002 10003 10004 10005 10006
{
  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)
    {
10007
      /* Create new top level AND item */
unknown's avatar
unknown committed
10008 10009 10010 10011 10012 10013 10014 10015 10016 10017 10018 10019 10020 10021 10022 10023 10024
      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
10025 10026 10027 10028 10029 10030 10031
	/*
	  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
10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 10046 10047 10048 10049
	  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
10050 10051 10052 10053 10054 10055
      /*
	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;
10056
      new_cond->top_level_item();
unknown's avatar
unknown committed
10057 10058 10059 10060 10061
      return new_cond;
    }
  }

  /*
10062 10063 10064
    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
10065 10066 10067 10068 10069 10070 10071 10072 10073 10074 10075 10076 10077 10078 10079 10080 10081 10082 10083 10084 10085 10086 10087 10088 10089 10090 10091 10092 10093 10094 10095
  */

  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)
{
10096 10097 10098
  if (!table->reginfo.join_tab)
    return (Item*) 0;             // field from outer non-select (UPDATE,...)

unknown's avatar
unknown committed
10099 10100 10101 10102 10103 10104 10105 10106
  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) &&
10107
	  !(key_part->key_part_flag & HA_PART_KEY_SEG))
unknown's avatar
unknown committed
10108 10109 10110 10111 10112 10113 10114
	return table->reginfo.join_tab->ref.items[part];
  }
  return (Item*) 0;
}


/*****************************************************************************
10115
  Test if one can use the key to resolve ORDER BY
10116 10117 10118 10119 10120 10121 10122 10123 10124 10125 10126 10127 10128 10129 10130 10131 10132

  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
10133 10134
*****************************************************************************/

unknown's avatar
unknown committed
10135 10136
static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
				uint *used_key_parts)
unknown's avatar
unknown committed
10137 10138 10139 10140 10141 10142
{
  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
10143
  DBUG_ENTER("test_if_order_by_key");
unknown's avatar
unknown committed
10144 10145 10146 10147 10148 10149 10150 10151 10152 10153

  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
10154 10155 10156
    for (; const_key_parts & 1 ; const_key_parts>>= 1)
      key_part++; 

unknown's avatar
unknown committed
10157
    if (key_part == key_part_end || key_part->field != field)
unknown's avatar
af  
unknown committed
10158
      DBUG_RETURN(0);
unknown's avatar
unknown committed
10159 10160

    /* set flag to 1 if we can use read-next on key, else to -1 */
10161 10162
    flag= ((order->asc == !(key_part->key_part_flag & HA_REVERSE_SORT)) ?
           1 : -1);
unknown's avatar
unknown committed
10163
    if (reverse && flag != reverse)
unknown's avatar
af  
unknown committed
10164
      DBUG_RETURN(0);
unknown's avatar
unknown committed
10165 10166 10167
    reverse=flag;				// Remember if reverse
    key_part++;
  }
unknown's avatar
unknown committed
10168
  *used_key_parts= (uint) (key_part - table->key_info[idx].key_part);
10169 10170 10171
  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
10172
  DBUG_RETURN(reverse);
unknown's avatar
unknown committed
10173 10174
}

unknown's avatar
af  
unknown committed
10175

10176
uint find_shortest_key(TABLE *table, const key_map *usable_keys)
unknown's avatar
unknown committed
10177 10178 10179
{
  uint min_length= (uint) ~0;
  uint best= MAX_KEY;
unknown's avatar
unknown committed
10180
  if (!usable_keys->is_clear_all())
unknown's avatar
unknown committed
10181
  {
unknown's avatar
unknown committed
10182
    for (uint nr=0; nr < table->keys ; nr++)
unknown's avatar
unknown committed
10183
    {
unknown's avatar
unknown committed
10184
      if (usable_keys->is_set(nr))
unknown's avatar
unknown committed
10185
      {
10186 10187 10188 10189 10190
        if (table->key_info[nr].key_length < min_length)
        {
          min_length=table->key_info[nr].key_length;
          best=nr;
        }
unknown's avatar
unknown committed
10191 10192 10193 10194 10195 10196
      }
    }
  }
  return best;
}

10197
/*
unknown's avatar
af  
unknown committed
10198 10199
  Test if a second key is the subkey of the first one.

10200 10201
  SYNOPSIS
    is_subkey()
unknown's avatar
af  
unknown committed
10202 10203 10204 10205
    key_part		First key parts
    ref_key_part	Second key parts
    ref_key_part_end	Last+1 part of the second key

10206 10207
  NOTE
    Second key MUST be shorter than the first one.
unknown's avatar
af  
unknown committed
10208

10209
  RETURN
unknown's avatar
af  
unknown committed
10210 10211
    1	is a subkey
    0	no sub key
10212 10213 10214 10215 10216 10217 10218 10219 10220 10221 10222 10223 10224
*/

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
10225 10226
  Test if we can use one of the 'usable_keys' instead of 'ref' key for sorting

10227 10228
  SYNOPSIS
    test_if_subkey()
unknown's avatar
af  
unknown committed
10229 10230 10231
    ref			Number of key, used for WHERE clause
    usable_keys		Keys for testing

10232
  RETURN
unknown's avatar
af  
unknown committed
10233 10234
    MAX_KEY			If we can't use other key
    the number of found key	Otherwise
10235 10236 10237
*/

static uint
unknown's avatar
unknown committed
10238
test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
unknown's avatar
af  
unknown committed
10239
	       const key_map *usable_keys)
10240 10241 10242 10243 10244 10245 10246
{
  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;
10247

unknown's avatar
unknown committed
10248
  for (nr= 0 ; nr < table->keys ; nr++)
10249
  {
unknown's avatar
af  
unknown committed
10250
    if (usable_keys->is_set(nr) &&
10251 10252 10253 10254 10255 10256 10257 10258 10259 10260 10261 10262
	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
10263

10264 10265 10266 10267 10268 10269 10270 10271 10272 10273
/*
  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
10274 10275

static bool
10276 10277
test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
			bool no_changes)
unknown's avatar
unknown committed
10278 10279
{
  int ref_key;
unknown's avatar
unknown committed
10280
  uint ref_key_parts;
unknown's avatar
unknown committed
10281 10282 10283 10284
  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
10285
  LINT_INIT(ref_key_parts);
unknown's avatar
unknown committed
10286 10287

  /* Check which keys can be used to resolve ORDER BY */
10288
  usable_keys.set_all();
unknown's avatar
unknown committed
10289 10290 10291 10292
  for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
  {
    if ((*tmp_order->item)->type() != Item::FIELD_ITEM)
    {
10293
      usable_keys.clear_all();
unknown's avatar
af  
unknown committed
10294
      DBUG_RETURN(0);
unknown's avatar
unknown committed
10295
    }
unknown's avatar
af  
unknown committed
10296 10297
    usable_keys.intersect(((Item_field*) (*tmp_order->item))->
			  field->part_of_sortkey);
unknown's avatar
unknown committed
10298
    if (usable_keys.is_clear_all())
unknown's avatar
af  
unknown committed
10299
      DBUG_RETURN(0);					// No usable keys
unknown's avatar
unknown committed
10300 10301 10302
  }

  ref_key= -1;
10303
  /* Test if constant range in WHERE */
unknown's avatar
af  
unknown committed
10304
  if (tab->ref.key >= 0 && tab->ref.key_parts)
unknown's avatar
unknown committed
10305 10306 10307
  {
    ref_key=	   tab->ref.key;
    ref_key_parts= tab->ref.key_parts;
10308 10309
    if (tab->type == JT_REF_OR_NULL)
      DBUG_RETURN(0);
unknown's avatar
unknown committed
10310
  }
unknown's avatar
unknown committed
10311
  else if (select && select->quick)		// Range found by opt_range
unknown's avatar
unknown committed
10312
  {
unknown's avatar
af  
unknown committed
10313 10314 10315 10316 10317 10318 10319 10320 10321 10322
    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
10323
      DBUG_RETURN(0);
unknown's avatar
unknown committed
10324 10325 10326
    ref_key=	   select->quick->index;
    ref_key_parts= select->quick->used_key_parts;
  }
unknown's avatar
unknown committed
10327 10328 10329

  if (ref_key >= 0)
  {
10330 10331 10332
    /*
      We come here when there is a REF key.
    */
10333
    int order_direction;
unknown's avatar
unknown committed
10334
    uint used_key_parts;
10335
    if (!usable_keys.is_set(ref_key))
10336 10337 10338 10339
    {
      /*
	We come here when ref_key is not among usable_keys
      */
unknown's avatar
unknown committed
10340 10341 10342 10343 10344
      uint new_ref_key;
      /*
	If using index only read, only consider other possible index only
	keys
      */
10345
      if (table->used_keys.is_set(ref_key))
unknown's avatar
af  
unknown committed
10346
	usable_keys.intersect(table->used_keys);
unknown's avatar
unknown committed
10347
      if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
unknown's avatar
af  
unknown committed
10348
				       &usable_keys)) < MAX_KEY)
10349
      {
unknown's avatar
unknown committed
10350
	/* Found key that can be used to retrieve data in sorted order */
10351 10352
	if (tab->ref.key >= 0)
	{
unknown's avatar
unknown committed
10353
	  tab->ref.key= new_ref_key;
10354 10355 10356
	}
	else
	{
unknown's avatar
unknown committed
10357
          select->quick->head->file->ha_index_end();
unknown's avatar
unknown committed
10358 10359 10360 10361
          /* 
            We have verified above that select->quick is not 
            index_merge quick select. 
          */
unknown's avatar
unknown committed
10362
	  select->quick->index= new_ref_key;
10363 10364
	  select->quick->init();
	}
unknown's avatar
unknown committed
10365
	ref_key= new_ref_key;
10366
      }
10367
    }
unknown's avatar
unknown committed
10368
    /* Check if we get the rows in requested sorted order by using the key */
10369
    if (usable_keys.is_set(ref_key) &&
unknown's avatar
unknown committed
10370 10371
	(order_direction = test_if_order_by_key(order,table,ref_key,
						&used_key_parts)))
10372
    {
10373
      if (order_direction == -1)		// If ORDER BY ... DESC
10374
      {
unknown's avatar
unknown committed
10375 10376
	if (select && select->quick)
	{
10377 10378 10379 10380 10381
	  /*
	    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
10382
	  {
unknown's avatar
af  
unknown committed
10383
            int quick_type= select->quick->get_type();
unknown's avatar
unknown committed
10384
            if (quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE ||
unknown's avatar
af  
unknown committed
10385
                quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT ||
10386 10387
                quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
                quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
unknown's avatar
unknown committed
10388
              DBUG_RETURN(0);                   // Use filesort
unknown's avatar
unknown committed
10389
            
unknown's avatar
unknown committed
10390
            /* ORDER BY range_key DESC */
unknown's avatar
unknown committed
10391
	    QUICK_SELECT_DESC *tmp=new QUICK_SELECT_DESC((QUICK_RANGE_SELECT*)(select->quick),
10392 10393 10394 10395 10396 10397 10398
							 used_key_parts);
	    if (!tmp || tmp->error)
	    {
	      delete tmp;
	      DBUG_RETURN(0);		// Reverse sort not supported
	    }
	    select->quick=tmp;
unknown's avatar
unknown committed
10399 10400 10401 10402 10403 10404 10405
	  }
	  DBUG_RETURN(1);
	}
	if (tab->ref.key_parts < used_key_parts)
	{
	  /*
	    SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
10406 10407 10408

	    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
10409
	  */
10410 10411 10412
	  tab->read_first_record=       join_read_last_key;
	  tab->read_record.read_record= join_read_prev_same;
	  /* fall through */
unknown's avatar
unknown committed
10413
	}
10414
      }
unknown's avatar
af  
unknown committed
10415 10416
      else if (select && select->quick)
	  select->quick->sorted= 1;
unknown's avatar
unknown committed
10417
      DBUG_RETURN(1);			/* No need to sort */
10418
    }
unknown's avatar
unknown committed
10419 10420 10421 10422 10423 10424
  }
  else
  {
    /* check if we can use a key to resolve the group */
    /* Tables using JT_NEXT are handled here */
    uint nr;
10425
    key_map keys;
unknown's avatar
unknown committed
10426 10427 10428 10429 10430 10431 10432

    /*
      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)
10433
    {
unknown's avatar
af  
unknown committed
10434
      keys= *table->file->keys_to_use_for_scanning();
10435
      keys.merge(table->used_keys);
unknown's avatar
af  
unknown committed
10436 10437

      /*
10438
	We are adding here also the index specified in FORCE INDEX clause, 
unknown's avatar
af  
unknown committed
10439
	if any.
10440
        This is to allow users to use index in ORDER BY.
unknown's avatar
af  
unknown committed
10441 10442 10443 10444
      */
      if (table->force_index) 
	keys.merge(table->keys_in_use_for_query);
      keys.intersect(usable_keys);
10445 10446
    }
    else
unknown's avatar
af  
unknown committed
10447
      keys= usable_keys;
unknown's avatar
unknown committed
10448

unknown's avatar
unknown committed
10449
    for (nr=0; nr < table->keys ; nr++)
unknown's avatar
unknown committed
10450
    {
unknown's avatar
unknown committed
10451
      uint not_used;
10452
      if (keys.is_set(nr))
unknown's avatar
unknown committed
10453 10454
      {
	int flag;
unknown's avatar
unknown committed
10455
	if ((flag= test_if_order_by_key(order, table, nr, &not_used)))
unknown's avatar
unknown committed
10456
	{
10457 10458 10459
	  if (!no_changes)
	  {
	    tab->index=nr;
10460 10461
	    tab->read_first_record=  (flag > 0 ? join_read_first:
				      join_read_last);
10462
	    tab->type=JT_NEXT;	// Read with index_first(), index_next()
10463
	    if (table->used_keys.is_set(nr))
unknown's avatar
unknown committed
10464 10465 10466 10467
	    {
	      table->key_read=1;
	      table->file->extra(HA_EXTRA_KEYREAD);
	    }
10468
	  }
unknown's avatar
unknown committed
10469 10470 10471 10472 10473 10474 10475 10476
	  DBUG_RETURN(1);
	}
      }
    }
  }
  DBUG_RETURN(0);				// Can't use index.
}

unknown's avatar
unknown committed
10477

unknown's avatar
unknown committed
10478
/*
unknown's avatar
unknown committed
10479
  If not selecting by given key, create an index how records should be read
unknown's avatar
unknown committed
10480 10481 10482 10483 10484 10485 10486 10487

  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
10488
		        Used to decide if we should use index or not
unknown's avatar
unknown committed
10489 10490 10491 10492 10493 10494 10495 10496 10497 10498 10499 10500 10501 10502 10503


  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
10504

unknown's avatar
unknown committed
10505
static int
10506
create_sort_index(THD *thd, JOIN *join, ORDER *order,
unknown's avatar
unknown committed
10507
		  ha_rows filesort_limit, ha_rows select_limit)
unknown's avatar
unknown committed
10508 10509 10510
{
  SORT_FIELD *sortorder;
  uint length;
10511
  ha_rows examined_rows;
10512 10513 10514
  TABLE *table;
  SQL_SELECT *select;
  JOIN_TAB *tab;
unknown's avatar
unknown committed
10515 10516
  DBUG_ENTER("create_sort_index");

10517 10518 10519 10520 10521 10522
  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;

10523
  if (test_if_skip_sort_order(tab,order,select_limit,0))
unknown's avatar
unknown committed
10524 10525 10526 10527
    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
10528 10529
  table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
                                             MYF(MY_WME | MY_ZEROFILL));
unknown's avatar
unknown committed
10530 10531 10532 10533 10534 10535 10536 10537 10538
  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
10539 10540 10541 10542 10543
      /* 
        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
10544 10545 10546 10547 10548 10549 10550 10551 10552 10553
      {
	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.
10554 10555
	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
10556
      */
unknown's avatar
af  
unknown committed
10557 10558 10559
      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
10560 10561 10562
	goto err;
    }
  }
10563 10564
  if (table->tmp_table)
    table->file->info(HA_STATUS_VARIABLE);	// Get record count
unknown's avatar
unknown committed
10565 10566
  table->sort.found_records=filesort(thd, table,sortorder, length,
                                     select, filesort_limit, &examined_rows);
unknown's avatar
af  
unknown committed
10567 10568 10569 10570 10571 10572
  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
10573
  tab->select_cond=0;
10574 10575
  tab->last_inner= 0;
  tab->first_unmatched= 0;
unknown's avatar
unknown committed
10576 10577
  tab->type=JT_ALL;				// Read with normal read_record
  tab->read_first_record= join_init_read_record;
10578
  tab->join->examined_rows+=examined_rows;
unknown's avatar
unknown committed
10579 10580 10581 10582 10583
  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
10584
  DBUG_RETURN(table->sort.found_records == HA_POS_ERROR);
unknown's avatar
unknown committed
10585 10586 10587 10588
err:
  DBUG_RETURN(-1);
}

10589
/*
10590
  Add the HAVING criteria to table->select
10591 10592
*/

unknown's avatar
unknown committed
10593
#ifdef NOT_YET
10594 10595 10596 10597 10598 10599
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
10600
  DBUG_EXECUTE("where",print_where(*having,"having"););
10601 10602 10603 10604 10605 10606 10607 10608 10609
  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
10610 10611 10612 10613
      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))
10614 10615
	return 1;
    table->select_cond=table->select->cond;
10616
    table->select_cond->top_level_item();
10617 10618 10619 10620 10621 10622 10623
    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
10624
#endif
10625 10626


unknown's avatar
unknown committed
10627
/*****************************************************************************
10628 10629 10630 10631 10632
  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
10633 10634 10635 10636 10637 10638 10639 10640 10641 10642 10643 10644 10645 10646 10647 10648 10649 10650 10651 10652 10653 10654 10655 10656 10657 10658 10659 10660 10661 10662 10663 10664 10665 10666
*****************************************************************************/

static bool compare_record(TABLE *table, Field **ptr)
{
  for (; *ptr ; ptr++)
  {
    if ((*ptr)->cmp_offset(table->rec_buff_length))
      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
10667
remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
unknown's avatar
unknown committed
10668 10669 10670 10671
{
  int error;
  ulong reclength,offset;
  uint field_count;
10672
  THD *thd= join->thd;
unknown's avatar
unknown committed
10673 10674 10675 10676 10677 10678 10679 10680 10681
  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
10682
  {
10683
    if (item->get_tmp_table_field() && ! item->const_item())
unknown's avatar
unknown committed
10684
      field_count++;
unknown's avatar
unknown committed
10685
  }
unknown's avatar
unknown committed
10686 10687 10688

  if (!field_count)
  {						// only const items
10689
    join->unit->select_limit_cnt= 1;		// Only send first row
unknown's avatar
unknown committed
10690 10691 10692 10693 10694 10695 10696 10697 10698 10699
    DBUG_RETURN(0);
  }
  Field **first_field=entry->field+entry->fields - field_count;
  offset=entry->field[entry->fields - field_count]->offset();
  reclength=entry->reclength-offset;

  free_io_cache(entry);				// Safety
  entry->file->info(HA_STATUS_VARIABLE);
  if (entry->db_type == DB_TYPE_HEAP ||
      (!entry->blob_fields &&
unknown's avatar
unknown committed
10700
       ((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->file->records <
10701
	thd->variables.sortbuff_size)))
unknown's avatar
unknown committed
10702 10703
    error=remove_dup_with_hash_index(join->thd, entry,
				     field_count, first_field,
10704
				     reclength, having);
unknown's avatar
unknown committed
10705
  else
10706 10707
    error=remove_dup_with_compare(join->thd, entry, first_field, offset,
				  having);
unknown's avatar
unknown committed
10708 10709 10710 10711 10712 10713 10714

  free_blobs(first_field);
  DBUG_RETURN(error);
}


static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
10715
				   ulong offset, Item *having)
unknown's avatar
unknown committed
10716 10717 10718
{
  handler *file=table->file;
  char *org_record,*new_record;
unknown's avatar
unknown committed
10719
  byte *record;
unknown's avatar
unknown committed
10720 10721 10722 10723
  int error;
  ulong reclength=table->reclength-offset;
  DBUG_ENTER("remove_dup_with_compare");

10724
  org_record=(char*) (record=table->record[0])+offset;
unknown's avatar
unknown committed
10725 10726
  new_record=(char*) table->record[1]+offset;

10727
  file->ha_rnd_init(1);
10728
  error=file->rnd_next(record);
unknown's avatar
unknown committed
10729 10730 10731 10732
  for (;;)
  {
    if (thd->killed)
    {
unknown's avatar
SCRUM  
unknown committed
10733
      thd->send_kill_message();
unknown's avatar
unknown committed
10734 10735 10736 10737 10738 10739 10740 10741 10742 10743 10744
      error=0;
      goto err;
    }
    if (error)
    {
      if (error == HA_ERR_RECORD_DELETED)
	continue;
      if (error == HA_ERR_END_OF_FILE)
	break;
      goto err;
    }
10745 10746 10747 10748
    if (having && !having->val_int())
    {
      if ((error=file->delete_row(record)))
	goto err;
10749
      error=file->rnd_next(record);
10750 10751
      continue;
    }
unknown's avatar
unknown committed
10752 10753
    if (copy_blobs(first_field))
    {
unknown's avatar
unknown committed
10754
      my_message(ER_OUTOFMEMORY, ER(ER_OUTOFMEMORY), MYF(0));
unknown's avatar
unknown committed
10755 10756 10757 10758 10759 10760 10761 10762 10763
      error=0;
      goto err;
    }
    memcpy(new_record,org_record,reclength);

    /* Read through rest of file and mark duplicated rows deleted */
    bool found=0;
    for (;;)
    {
10764
      if ((error=file->rnd_next(record)))
unknown's avatar
unknown committed
10765 10766 10767 10768 10769 10770 10771 10772 10773
      {
	if (error == HA_ERR_RECORD_DELETED)
	  continue;
	if (error == HA_ERR_END_OF_FILE)
	  break;
	goto err;
      }
      if (compare_record(table, first_field) == 0)
      {
10774
	if ((error=file->delete_row(record)))
unknown's avatar
unknown committed
10775 10776 10777 10778 10779
	  goto err;
      }
      else if (!found)
      {
	found=1;
10780
	file->position(record);	// Remember position
unknown's avatar
unknown committed
10781 10782 10783 10784 10785
      }
    }
    if (!found)
      break;					// End of file
    /* Restart search on next row */
10786
    error=file->restart_rnd_next(record,file->ref);
unknown's avatar
unknown committed
10787 10788 10789 10790 10791 10792 10793 10794 10795 10796 10797 10798 10799 10800 10801 10802 10803 10804 10805 10806
  }

  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,
10807 10808
				      ulong key_length,
				      Item *having)
unknown's avatar
unknown committed
10809 10810 10811 10812 10813 10814 10815 10816 10817 10818 10819 10820 10821 10822 10823 10824 10825
{
  byte *key_buffer, *key_pos, *record=table->record[0];
  int error;
  handler *file=table->file;
  ulong extra_length=ALIGN_SIZE(key_length)-key_length;
  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
10826

unknown's avatar
unknown committed
10827
  if (hash_init(&hash, &my_charset_bin, (uint) file->records, 0, 
unknown's avatar
unknown committed
10828
		key_length,(hash_get_key) 0, 0, 0))
unknown's avatar
unknown committed
10829 10830 10831 10832 10833 10834 10835 10836 10837 10838
  {
    my_free((char*) key_buffer,MYF(0));
    DBUG_RETURN(1);
  }
  {
    Field **ptr;
    for (ptr= first_field, field_length=field_lengths ; *ptr ; ptr++)
      (*field_length++)= (*ptr)->pack_length();
  }

10839
  file->ha_rnd_init(1);
unknown's avatar
unknown committed
10840 10841 10842 10843 10844
  key_pos=key_buffer;
  for (;;)
  {
    if (thd->killed)
    {
unknown's avatar
SCRUM  
unknown committed
10845
      thd->send_kill_message();
unknown's avatar
unknown committed
10846 10847 10848 10849 10850 10851 10852 10853 10854 10855 10856
      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;
    }
10857 10858 10859 10860 10861
    if (having && !having->val_int())
    {
      if ((error=file->delete_row(record)))
	goto err;
      continue;
10862
    }
unknown's avatar
unknown committed
10863 10864 10865 10866 10867 10868 10869 10870 10871 10872 10873 10874 10875 10876 10877

    /* copy fields to key buffer */
    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 */
    if (hash_search(&hash,key_pos-key_length,key_length))
    {
      /* Duplicated found ; Remove the row */
      if ((error=file->delete_row(record)))
	goto err;
    }
10878
    else
unknown's avatar
SCRUM  
unknown committed
10879
      (void) my_hash_insert(&hash, key_pos-key_length);
unknown's avatar
unknown committed
10880 10881 10882 10883 10884
    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
10885
  (void) file->ha_rnd_end();
unknown's avatar
unknown committed
10886 10887 10888 10889 10890 10891
  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
10892
  (void) file->ha_rnd_end();
unknown's avatar
unknown committed
10893 10894 10895 10896 10897 10898
  if (error)
    file->print_error(error,MYF(0));
  DBUG_RETURN(1);
}


unknown's avatar
unknown committed
10899
SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
unknown's avatar
unknown committed
10900 10901 10902 10903 10904 10905 10906 10907 10908 10909 10910 10911 10912 10913 10914 10915 10916 10917 10918
{
  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())
10919
      pos->field= ((Item_sum*) order->item[0])->get_tmp_table_field();
unknown's avatar
unknown committed
10920 10921 10922 10923 10924 10925 10926 10927 10928 10929 10930 10931 10932 10933
    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);
}


/*****************************************************************************
10934 10935 10936 10937
  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
10938 10939 10940 10941 10942 10943 10944 10945 10946
******************************************************************************/

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;
10947
  JOIN_TAB *join_tab;
unknown's avatar
unknown committed
10948 10949 10950 10951 10952
  DBUG_ENTER("join_init_cache");

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

10953 10954
  join_tab=tables;
  for (i=0 ; i < table_count ; i++,join_tab++)
unknown's avatar
unknown committed
10955
  {
10956 10957 10958 10959
    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
10960 10961 10962
  }
  if (!(cache->field=(CACHE_FIELD*)
	sql_alloc(sizeof(CACHE_FIELD)*(cache->fields+table_count*2)+(blobs+1)*
unknown's avatar
unknown committed
10963

unknown's avatar
unknown committed
10964 10965 10966 10967 10968 10969 10970 10971 10972 10973 10974 10975 10976 10977 10978 10979 10980 10981 10982 10983 10984 10985 10986 10987 10988 10989 10990 10991 10992 10993 10994 10995 10996 10997 10998 10999
		  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 */
    if (null_fields && tables[i].table->null_fields)
    {						/* must copy null bits */
      copy->str=(char*) tables[i].table->null_flags;
11000
      copy->length=tables[i].table->null_bytes;
unknown's avatar
unknown committed
11001 11002 11003 11004 11005 11006 11007 11008 11009 11010 11011 11012 11013 11014 11015 11016 11017 11018 11019 11020 11021 11022
      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 */
11023
  size=max(thd->variables.join_buff_size, cache->length);
unknown's avatar
unknown committed
11024 11025 11026
  if (!(cache->buff=(uchar*) my_malloc(size,MYF(0))))
    DBUG_RETURN(1);				/* Don't use cache */ /* purecov: inspected */
  cache->end=cache->buff+size;
11027
  reset_cache_write(cache);
unknown's avatar
unknown committed
11028 11029 11030 11031 11032 11033 11034 11035 11036 11037 11038 11039 11040 11041 11042 11043 11044 11045 11046 11047 11048 11049 11050 11051 11052 11053 11054 11055 11056 11057 11058 11059 11060 11061 11062 11063
  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;

  /*
11064
    There is room in cache. Put record there
unknown's avatar
unknown committed
11065 11066 11067 11068 11069 11070 11071 11072
  */
  cache->records++;
  for (copy=cache->field ; copy < end_field; copy++)
  {
    if (copy->blob_field)
    {
      if (last_record)
      {
unknown's avatar
unknown committed
11073 11074
	copy->blob_field->get_image((char*) pos,copy->length+sizeof(char*), 
				    copy->blob_field->charset());
unknown's avatar
unknown committed
11075 11076 11077 11078
	pos+=copy->length+sizeof(char*);
      }
      else
      {
unknown's avatar
unknown committed
11079 11080
	copy->blob_field->get_image((char*) pos,copy->length, // blob length
				    copy->blob_field->charset());
unknown's avatar
unknown committed
11081 11082 11083 11084 11085 11086 11087 11088 11089 11090 11091 11092 11093 11094 11095 11096 11097 11098 11099 11100 11101 11102 11103 11104 11105 11106 11107 11108 11109 11110
	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
11111
reset_cache_read(JOIN_CACHE *cache)
unknown's avatar
unknown committed
11112 11113 11114 11115 11116 11117
{
  cache->record_nr=0;
  cache->pos=cache->buff;
}


11118 11119 11120 11121 11122
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
11123 11124 11125 11126 11127 11128 11129 11130 11131 11132 11133 11134 11135 11136 11137 11138 11139 11140 11141 11142 11143 11144
}


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
11145 11146
	copy->blob_field->set_image((char*) pos,copy->length+sizeof(char*),
				    copy->blob_field->charset());
unknown's avatar
unknown committed
11147 11148 11149 11150 11151 11152 11153 11154 11155 11156 11157 11158 11159 11160 11161 11162 11163 11164 11165 11166 11167 11168 11169 11170 11171 11172 11173 11174 11175 11176 11177 11178 11179 11180 11181 11182 11183 11184 11185 11186 11187 11188 11189 11190 11191 11192 11193 11194 11195 11196 11197 11198 11199 11200
	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);
  }
  if ((tab->ref.key_err=cp_buffer_from_ref(&tab->ref)) || diff)
    return 1;
  return memcmp(tab->ref.key_buff2, tab->ref.key_buff, tab->ref.key_length)
    != 0;
}


bool
cp_buffer_from_ref(TABLE_REF *ref)
{
  for (store_key **copy=ref->key_copy ; *copy ; copy++)
    if ((*copy)->copy())
      return 1;					// Something went wrong
  return 0;
}


/*****************************************************************************
11201
  Group and order functions
unknown's avatar
unknown committed
11202 11203 11204
*****************************************************************************/

/*
11205 11206 11207 11208 11209 11210 11211 11212 11213 11214 11215 11216 11217 11218 11219 11220 11221 11222 11223 11224 11225 11226 11227 11228 11229 11230
  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
11231
    0 if OK
11232
    1 if error occurred
unknown's avatar
unknown committed
11233 11234 11235
*/

static int
11236 11237 11238
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
11239
{
11240
  Item *order_item= *order->item; /* The item from the GROUP/ORDER caluse. */
11241 11242 11243 11244 11245
  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
11246
  {						/* Order by position */
11247
    uint count= (uint) order_item->val_int();
unknown's avatar
unknown committed
11248
    if (!count || count > fields.elements)
unknown's avatar
unknown committed
11249
    {
11250 11251
      my_error(ER_BAD_FIELD_ERROR, MYF(0),
               order_item->full_name(), thd->where);
unknown's avatar
unknown committed
11252 11253
      return 1;
    }
11254
    order->item= ref_pointer_array + count - 1;
11255
    order->in_field_list= 1;
11256 11257
    order->counter= count;
    order->counter_used= 1;
unknown's avatar
unknown committed
11258 11259
    return 0;
  }
11260
  /* Lookup the current GROUP/ORDER field in the SELECT clause. */
11261
  uint counter;
11262
  bool unaliased;
11263
  select_item= find_item_in_list(order_item, fields, &counter,
11264
                                 REPORT_EXCEPT_NOT_FOUND, &unaliased);
11265 11266
  if (!select_item)
    return 1; /* Some error occured. */
11267 11268


11269 11270
  /* Check whether the resolved field is not ambiguos. */
  if (select_item != not_found_item)
unknown's avatar
unknown committed
11271
  {
11272 11273 11274 11275 11276
    /*
      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).
    */
11277
    if (unaliased && !order_item->fixed && order_item->fix_fields(thd, tables, order->item))
11278 11279
      return 1;

11280 11281 11282 11283 11284 11285 11286 11287 11288 11289 11290 11291 11292 11293 11294 11295 11296 11297 11298 11299 11300 11301 11302 11303 11304 11305 11306 11307 11308 11309
    /* Lookup the current GROUP field in the FROM clause. */
    order_item_type= order_item->type();
    if (is_group_field &&
        order_item_type == Item::FIELD_ITEM || order_item_type == Item::REF_ITEM)
    {
      Item **view_ref= NULL;
      from_field= find_field_in_tables(thd, (Item_ident*) order_item, tables,
                                       view_ref, IGNORE_ERRORS, TRUE);
      if(!from_field)
       from_field= (Field*) not_found_field;
    }
    else
      from_field= (Field*) not_found_field;

    if (from_field == not_found_field ||
        from_field && from_field != view_ref_found &&
        (*select_item)->type() == Item::FIELD_ITEM &&
        ((Item_field*) (*select_item))->field->eq(from_field))
      /*
        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
11310
  }
11311

unknown's avatar
unknown committed
11312
  order->in_field_list=0;
unknown's avatar
af  
unknown committed
11313
  /*
11314
    We check order_item->fixed because Item_func_group_concat can put
unknown's avatar
af  
unknown committed
11315 11316 11317 11318
    arguments for which fix_fields already was called.

    'it' reassigned in if condition because fix_field can change it.
  */
11319 11320 11321
  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
11322
       thd->is_fatal_error))
11323
    return 1;					// Wrong field 
11324
  uint el= all_fields.elements;
unknown's avatar
unknown committed
11325 11326
  all_fields.push_front(order_item);		        // Add new field to field list
  ref_pointer_array[el]= order_item;
11327
  order->item= ref_pointer_array + el;
unknown's avatar
unknown committed
11328 11329 11330
  return 0;
}

11331

unknown's avatar
unknown committed
11332
/*
11333 11334
  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
11335 11336
*/

11337 11338
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
11339 11340 11341 11342
{
  thd->where="order clause";
  for (; order; order=order->next)
  {
11343
    if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
11344
			   all_fields, FALSE))
unknown's avatar
unknown committed
11345 11346 11347 11348 11349 11350
      return 1;
  }
  return 0;
}


unknown's avatar
af  
unknown committed
11351 11352 11353 11354 11355 11356 11357
/*
  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
11358
			'fields' here.
unknown's avatar
af  
unknown committed
11359 11360 11361 11362 11363 11364 11365 11366 11367 11368 11369 11370 11371 11372 11373
   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
11374
int
11375 11376 11377
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
11378 11379 11380 11381 11382
{
  *hidden_group_fields=0;
  if (!order)
    return 0;				/* Everything is ok */

11383
  if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
unknown's avatar
unknown committed
11384 11385 11386 11387 11388 11389 11390 11391 11392
  {
    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";
11393
  for (; order; order=order->next)
unknown's avatar
unknown committed
11394
  {
11395
    if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
11396
			   all_fields, TRUE))
unknown's avatar
unknown committed
11397 11398 11399 11400
      return 1;
    (*order->item)->marker=1;		/* Mark found */
    if ((*order->item)->with_sum_func)
    {
11401
      my_error(ER_WRONG_GROUP_FIELD, MYF(0), (*order->item)->full_name());
unknown's avatar
unknown committed
11402 11403 11404
      return 1;
    }
  }
11405
  if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
unknown's avatar
unknown committed
11406 11407 11408 11409 11410 11411 11412
  {
    /* Don't allow one to use fields that is not used in GROUP BY */
    Item *item;
    List_iterator<Item> li(fields);

    while ((item=li++))
    {
11413 11414
      if (item->type() != Item::SUM_FUNC_ITEM && !item->marker &&
	  !item->const_item())
unknown's avatar
unknown committed
11415
      {
11416
	my_error(ER_WRONG_FIELD_WITH_GROUP, MYF(0), item->full_name());
unknown's avatar
unknown committed
11417 11418 11419 11420 11421 11422 11423 11424 11425 11426
	return 1;
      }
    }
  }
  if (org_fields != all_fields.elements)
    *hidden_group_fields=1;			// group fields is not used
  return 0;
}

/*
11427
  Add fields with aren't used at start of field list. Return FALSE if ok
unknown's avatar
unknown committed
11428 11429 11430 11431 11432 11433 11434 11435 11436 11437
*/

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...
11438
  uint counter;
11439
  bool not_used;
unknown's avatar
unknown committed
11440
  for (; new_field ; new_field= new_field->next)
unknown's avatar
unknown committed
11441
  {
11442
    if ((item= find_item_in_list(*new_field->item, fields, &counter,
11443
				 IGNORE_ERRORS, &not_used)))
unknown's avatar
unknown committed
11444 11445 11446 11447
      new_field->item=item;			/* Change to shared Item */
    else
    {
      thd->where="procedure list";
unknown's avatar
unknown committed
11448
      if ((*new_field->item)->fix_fields(thd, tables, new_field->item))
unknown's avatar
unknown committed
11449 11450 11451 11452 11453 11454 11455 11456 11457
	DBUG_RETURN(1); /* purecov: inspected */
      all_fields.push_front(*new_field->item);
      new_field->item=all_fields.head_ref();
    }
  }
  DBUG_RETURN(0);
}

/*
11458 11459 11460
  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
11461 11462 11463
*/

static ORDER *
11464 11465
create_distinct_group(THD *thd, ORDER *order_list, List<Item> &fields, 
		      bool *all_order_by_fields_used)
unknown's avatar
unknown committed
11466 11467 11468 11469 11470
{
  List_iterator<Item> li(fields);
  Item *item;
  ORDER *order,*group,**prev;

11471
  *all_order_by_fields_used= 1;
unknown's avatar
unknown committed
11472 11473 11474 11475 11476 11477 11478 11479
  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)
    {
11480
      ORDER *ord=(ORDER*) thd->memdup((char*) order,sizeof(ORDER));
unknown's avatar
unknown committed
11481 11482 11483 11484 11485 11486
      if (!ord)
	return 0;
      *prev=ord;
      prev= &ord->next;
      (*ord->item)->marker=1;
    }
11487 11488
    else
      *all_order_by_fields_used= 0;
unknown's avatar
unknown committed
11489 11490 11491 11492 11493 11494 11495 11496 11497
  }

  li.rewind();
  while ((item=li++))
  {
    if (item->const_item() || item->with_sum_func)
      continue;
    if (!item->marker)
    {
11498
      ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER));
unknown's avatar
unknown committed
11499 11500 11501 11502 11503 11504 11505 11506 11507 11508 11509 11510 11511 11512
      if (!ord)
	return 0;
      ord->item=li.ref();
      ord->asc=1;
      *prev=ord;
      prev= &ord->next;
    }
  }
  *prev=0;
  return group;
}


/*****************************************************************************
11513
  Update join with count of the different type of fields
unknown's avatar
unknown committed
11514 11515 11516
*****************************************************************************/

void
unknown's avatar
unknown committed
11517 11518
count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
		  bool reset_with_sum_func)
unknown's avatar
unknown committed
11519 11520 11521 11522
{
  List_iterator<Item> li(fields);
  Item *field;

11523
  param->field_count=param->sum_func_count=param->func_count=
unknown's avatar
unknown committed
11524
    param->hidden_field_count=0;
unknown's avatar
unknown committed
11525 11526 11527 11528 11529 11530 11531 11532 11533 11534 11535 11536 11537 11538 11539 11540 11541 11542 11543 11544 11545 11546 11547 11548 11549
  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
11550
    {
unknown's avatar
unknown committed
11551
      param->func_count++;
unknown's avatar
unknown committed
11552 11553 11554
      if (reset_with_sum_func)
	field->with_sum_func=0;
    }
unknown's avatar
unknown committed
11555 11556 11557 11558 11559 11560 11561 11562 11563 11564 11565 11566 11567 11568 11569
  }
}


/*
  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)
  {
11570
    if ((*a->item)->eq(*b->item,1))
unknown's avatar
unknown committed
11571 11572 11573 11574 11575 11576 11577 11578 11579 11580 11581 11582 11583 11584 11585 11586 11587 11588 11589 11590 11591 11592 11593 11594 11595 11596
      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)
  {
11597
    if (!(*a->item)->eq(*b->item,1))
unknown's avatar
unknown committed
11598 11599 11600
      DBUG_RETURN(0);
    map|=a->item[0]->used_tables();
  }
unknown's avatar
unknown committed
11601
  if (!map || (map & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT)))
unknown's avatar
unknown committed
11602 11603
    DBUG_RETURN(0);

11604
  for (; !(map & tables->table->map); tables= tables->next_leaf);
unknown's avatar
unknown committed
11605 11606 11607 11608 11609 11610 11611 11612 11613 11614 11615 11616
  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)
{
11617 11618
  uint key_length=0, parts=0, null_parts=0;

unknown's avatar
unknown committed
11619 11620 11621 11622
  if (group)
    join->group= 1;
  for (; group ; group=group->next)
  {
11623
    Field *field=(*group->item)->get_tmp_table_field();
unknown's avatar
unknown committed
11624 11625 11626 11627 11628 11629 11630 11631 11632 11633 11634 11635 11636 11637 11638
    if (field)
    {
      if (field->type() == FIELD_TYPE_BLOB)
	key_length+=MAX_BLOB_WIDTH;		// Can't be used as a key
      else
	key_length+=field->pack_length();
    }
    else if ((*group->item)->result_type() == REAL_RESULT)
      key_length+=sizeof(double);
    else if ((*group->item)->result_type() == INT_RESULT)
      key_length+=sizeof(longlong);
    else
      key_length+=(*group->item)->max_length;
    parts++;
    if ((*group->item)->maybe_null)
11639
      null_parts++;
unknown's avatar
unknown committed
11640
  }
11641
  join->tmp_table_param.group_length=key_length+null_parts;
unknown's avatar
unknown committed
11642
  join->tmp_table_param.group_parts=parts;
11643
  join->tmp_table_param.group_null_parts=null_parts;
unknown's avatar
unknown committed
11644 11645
}

11646

11647
/*
11648
  allocate group fields or take prepared (cached)
11649

11650
  SYNOPSIS
11651 11652 11653 11654 11655 11656 11657 11658 11659 11660 11661 11662
    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)
{
11663 11664 11665 11666 11667 11668 11669 11670 11671 11672 11673 11674
  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);
11675
}
unknown's avatar
unknown committed
11676

11677

unknown's avatar
unknown committed
11678
/*
11679 11680
  Get a list of buffers for saveing last group
  Groups are saved in reverse order for easyer check loop
unknown's avatar
unknown committed
11681 11682 11683 11684 11685 11686 11687 11688 11689 11690 11691 11692 11693 11694 11695 11696 11697 11698 11699 11700 11701 11702
*/

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)
{
11703
  DBUG_ENTER("test_if_group_changed");
unknown's avatar
unknown committed
11704 11705 11706 11707 11708 11709 11710 11711 11712
  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;
  }
11713 11714
  DBUG_PRINT("info", ("idx: %d", idx));
  DBUG_RETURN(idx);
unknown's avatar
unknown committed
11715 11716 11717 11718
}


/*
11719
  Setup copy_fields to save fields at start of new group
unknown's avatar
unknown committed
11720 11721 11722 11723 11724 11725 11726 11727 11728 11729 11730 11731 11732 11733 11734 11735 11736 11737 11738

  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
11739 11740 11741
*/

bool
11742 11743
setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
		  Item **ref_pointer_array,
unknown's avatar
unknown committed
11744 11745
		  List<Item> &res_selected_fields, List<Item> &res_all_fields,
		  uint elements, List<Item> &all_fields)
unknown's avatar
unknown committed
11746 11747
{
  Item *pos;
unknown's avatar
unknown committed
11748
  List_iterator_fast<Item> li(all_fields);
unknown's avatar
unknown committed
11749
  Copy_field *copy;
unknown's avatar
unknown committed
11750 11751 11752 11753
  res_selected_fields.empty();
  res_all_fields.empty();
  List_iterator_fast<Item> itr(res_all_fields);
  uint i, border= all_fields.elements - elements;
unknown's avatar
af  
unknown committed
11754
  DBUG_ENTER("setup_copy_fields");
unknown's avatar
unknown committed
11755 11756

  if (!(copy=param->copy_field= new Copy_field[param->field_count]))
11757
    goto err2;
unknown's avatar
unknown committed
11758 11759

  param->copy_funcs.empty();
11760
  for (i= 0; (pos= li++); i++)
unknown's avatar
unknown committed
11761 11762 11763
  {
    if (pos->type() == Item::FIELD_ITEM)
    {
11764
      Item_field *item;
unknown's avatar
af  
unknown committed
11765
      if (!(item= new Item_field(thd, ((Item_field*) pos))))
11766 11767
	goto err;
      pos= item;
unknown's avatar
unknown committed
11768 11769
      if (item->field->flags & BLOB_FLAG)
      {
11770
	if (!(pos= new Item_copy_string(pos)))
unknown's avatar
unknown committed
11771
	  goto err;
11772 11773 11774 11775 11776 11777 11778 11779 11780 11781
       /*
         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
11782 11783
	  goto err;
      }
11784 11785 11786 11787 11788 11789 11790
      else
      {
	/* 
	   set up save buffer and change result_field to point at 
	   saved value
	*/
	Field *field= item->field;
unknown's avatar
unknown committed
11791
	item->result_field=field->new_field(thd->mem_root,field->table);
11792 11793 11794 11795 11796 11797 11798
	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
11799 11800
    }
    else if ((pos->type() == Item::FUNC_ITEM ||
11801 11802
	      pos->type() == Item::SUBSELECT_ITEM ||
	      pos->type() == Item::CACHE_ITEM ||
unknown's avatar
unknown committed
11803 11804 11805 11806 11807 11808 11809 11810 11811 11812 11813 11814 11815 11816
	      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;
      if (param->copy_funcs.push_back(pos))
	goto err;
    }
unknown's avatar
unknown committed
11817 11818
    res_all_fields.push_back(pos);
    ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
11819
      pos;
unknown's avatar
unknown committed
11820
  }
unknown's avatar
unknown committed
11821
  param->copy_field_end= copy;
11822 11823 11824

  for (i= 0; i < border; i++)
    itr++;
unknown's avatar
unknown committed
11825
  itr.sublist(res_selected_fields, elements);
unknown's avatar
unknown committed
11826 11827 11828
  DBUG_RETURN(0);

 err:
11829
  delete [] param->copy_field;			// This is never 0
unknown's avatar
unknown committed
11830
  param->copy_field=0;
11831
err2:
unknown's avatar
unknown committed
11832 11833 11834 11835 11836
  DBUG_RETURN(TRUE);
}


/*
11837 11838 11839 11840
  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
11841 11842 11843 11844 11845 11846
*/

void
copy_fields(TMP_TABLE_PARAM *param)
{
  Copy_field *ptr=param->copy_field;
unknown's avatar
unknown committed
11847
  Copy_field *end=param->copy_field_end;
unknown's avatar
unknown committed
11848

11849
  for (; ptr != end; ptr++)
unknown's avatar
unknown committed
11850 11851
    (*ptr->do_copy)(ptr);

unknown's avatar
unknown committed
11852 11853
  List_iterator_fast<Item> &it=param->copy_funcs_it;
  it.rewind();
unknown's avatar
unknown committed
11854 11855 11856 11857 11858 11859
  Item_copy_string *item;
  while ((item = (Item_copy_string*) it++))
    item->copy();
}


11860 11861
/*
  Make an array of pointers to sum_functions to speed up sum_func calculation
unknown's avatar
unknown committed
11862

11863 11864 11865 11866 11867 11868 11869 11870 11871
  SYNOPSIS
    alloc_func_list()

  RETURN
    0	ok
    1	Error
*/

bool JOIN::alloc_func_list()
unknown's avatar
unknown committed
11872
{
11873 11874 11875 11876 11877 11878 11879 11880 11881 11882 11883 11884 11885 11886 11887 11888 11889 11890 11891 11892 11893 11894 11895 11896 11897 11898 11899
  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
11900 11901 11902 11903 11904 11905 11906 11907
/*
  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
11908
    recompute           Set to TRUE if sum_funcs must be recomputed
unknown's avatar
af  
unknown committed
11909 11910 11911 11912 11913 11914

  RETURN
    0  ok
    1  error
*/

11915
bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
11916
			      bool before_group_by, bool recompute)
unknown's avatar
unknown committed
11917
{
11918
  List_iterator_fast<Item> it(field_list);
11919 11920
  Item_sum **func;
  Item *item;
unknown's avatar
unknown committed
11921 11922
  DBUG_ENTER("make_sum_func_list");

11923 11924 11925
  if (*sum_funcs && !recompute)
    DBUG_RETURN(FALSE); /* We have already initialized sum_funcs. */

11926 11927
  func= sum_funcs;
  while ((item=it++))
unknown's avatar
unknown committed
11928
  {
11929 11930
    if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
      *func++= (Item_sum*) item;
unknown's avatar
unknown committed
11931
  }
11932 11933 11934
  if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
  {
    rollup.state= ROLLUP::STATE_READY;
11935
    if (rollup_make_fields(field_list, send_fields, &func))
11936 11937 11938 11939 11940 11941 11942
      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
11943 11944 11945 11946 11947 11948
  *func=0;					// End marker
  DBUG_RETURN(FALSE);
}


/*
unknown's avatar
af  
unknown committed
11949
  Change all funcs and sum_funcs to fields in tmp table, and create
unknown's avatar
unknown committed
11950 11951 11952 11953 11954 11955 11956 11957 11958 11959 11960 11961 11962
  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
11963 11964 11965
*/

static bool
11966
change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
unknown's avatar
unknown committed
11967 11968 11969
			 List<Item> &res_selected_fields,
			 List<Item> &res_all_fields,
			 uint elements, List<Item> &all_fields)
unknown's avatar
unknown committed
11970
{
unknown's avatar
unknown committed
11971
  List_iterator_fast<Item> it(all_fields);
unknown's avatar
unknown committed
11972
  Item *item_field,*item;
unknown's avatar
unknown committed
11973 11974
  res_selected_fields.empty();
  res_all_fields.empty();
unknown's avatar
unknown committed
11975

unknown's avatar
unknown committed
11976
  uint i, border= all_fields.elements - elements;
11977
  for (i= 0; (item= it++); i++)
unknown's avatar
unknown committed
11978 11979
  {
    Field *field;
11980
    
unknown's avatar
unknown committed
11981
    if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
11982 11983
      item_field= item;
    else
unknown's avatar
unknown committed
11984
    {
11985
      if (item->type() == Item::FIELD_ITEM)
unknown's avatar
unknown committed
11986
      {
11987
	item_field= item->get_tmp_table_item(thd);
unknown's avatar
unknown committed
11988
      }
11989
      else if ((field= item->get_tmp_table_field()))
11990 11991 11992 11993 11994 11995 11996 11997 11998 11999 12000 12001
      {
	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)
	  return TRUE;				// Fatal error
	item_field->name= item->name;		/*lint -e613 */
#ifndef DBUG_OFF
	if (_db_on_ && !item_field->name)
	{
	  char buff[256];
12002
	  String str(buff,sizeof(buff),&my_charset_bin);
12003 12004 12005 12006
	  str.length(0);
	  item->print(&str);
	  item_field->name= sql_strmake(str.ptr(),str.length());
	}
unknown's avatar
unknown committed
12007
#endif
12008 12009 12010
      }
      else
	item_field= item;
unknown's avatar
unknown committed
12011 12012 12013
    }
    res_all_fields.push_back(item_field);
    ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
12014
      item_field;
unknown's avatar
unknown committed
12015
  }
12016

unknown's avatar
unknown committed
12017
  List_iterator_fast<Item> itr(res_all_fields);
12018 12019
  for (i= 0; i < border; i++)
    itr++;
unknown's avatar
unknown committed
12020
  itr.sublist(res_selected_fields, elements);
unknown's avatar
unknown committed
12021 12022 12023 12024 12025
  return FALSE;
}


/*
12026 12027
  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
12028 12029 12030 12031 12032 12033 12034 12035 12036 12037

  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
12038 12039
    0	ok
    1	error
unknown's avatar
unknown committed
12040 12041 12042
*/

static bool
12043
change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
unknown's avatar
unknown committed
12044 12045 12046
			  List<Item> &res_selected_fields,
			  List<Item> &res_all_fields, uint elements,
			  List<Item> &all_fields)
unknown's avatar
unknown committed
12047
{
unknown's avatar
unknown committed
12048
  List_iterator_fast<Item> it(all_fields);
12049
  Item *item, *new_item;
unknown's avatar
unknown committed
12050 12051
  res_selected_fields.empty();
  res_all_fields.empty();
unknown's avatar
unknown committed
12052

unknown's avatar
unknown committed
12053
  uint i, border= all_fields.elements - elements;
12054
  for (i= 0; (item= it++); i++)
unknown's avatar
unknown committed
12055
  {
unknown's avatar
unknown committed
12056 12057
    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)]=
12058
      new_item;
unknown's avatar
unknown committed
12059
  }
12060

unknown's avatar
unknown committed
12061
  List_iterator_fast<Item> itr(res_all_fields);
12062 12063
  for (i= 0; i < border; i++)
    itr++;
unknown's avatar
unknown committed
12064
  itr.sublist(res_selected_fields, elements);
12065

12066
  return thd->is_fatal_error;
unknown's avatar
unknown committed
12067 12068 12069 12070 12071
}



/******************************************************************************
12072
  Code for calculating functions
unknown's avatar
unknown committed
12073 12074
******************************************************************************/

12075 12076 12077 12078 12079 12080 12081 12082 12083 12084 12085 12086 12087 12088 12089 12090 12091 12092 12093 12094 12095 12096 12097 12098

/*
  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;
  while ((func= *(func_ptr++)))
    if (func->setup(thd))
      return TRUE;
  return FALSE;
}


unknown's avatar
unknown committed
12099 12100 12101 12102 12103 12104 12105 12106 12107 12108 12109 12110 12111 12112 12113 12114 12115
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
12116
    func->update_field();
unknown's avatar
unknown committed
12117 12118 12119 12120 12121 12122 12123 12124 12125 12126
}


	/* Copy result of sum functions to record in tmp_table */

static void
copy_sum_funcs(Item_sum **func_ptr)
{
  Item_sum *func;
  for (; (func = *func_ptr) ; func_ptr++)
unknown's avatar
unknown committed
12127
    (void) func->save_in_result_field(1);
unknown's avatar
unknown committed
12128 12129 12130 12131
  return;
}


12132 12133
static bool
init_sum_functions(Item_sum **func_ptr, Item_sum **end_ptr)
unknown's avatar
unknown committed
12134
{
12135 12136 12137 12138 12139 12140 12141 12142 12143 12144 12145 12146
  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
12147 12148 12149 12150 12151 12152 12153 12154 12155 12156 12157 12158 12159 12160 12161 12162
}


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
12163
copy_funcs(Item **func_ptr)
unknown's avatar
unknown committed
12164
{
unknown's avatar
unknown committed
12165
  Item *func;
unknown's avatar
unknown committed
12166
  for (; (func = *func_ptr) ; func_ptr++)
unknown's avatar
unknown committed
12167
    func->save_in_result_field(1);
unknown's avatar
unknown committed
12168 12169 12170
}


12171
/*
12172 12173
  Create a condition for a const reference and add this to the
  currenct select for the table
12174
*/
unknown's avatar
unknown committed
12175 12176 12177 12178 12179 12180 12181 12182 12183 12184 12185 12186 12187 12188 12189

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++)
  {
12190 12191
    Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i].
			      fieldnr-1];
unknown's avatar
unknown committed
12192
    Item *value=join_tab->ref.items[i];
unknown's avatar
af  
unknown committed
12193
    cond->add(new Item_func_equal(new Item_field(field), value));
unknown's avatar
unknown committed
12194
  }
12195
  if (thd->is_fatal_error)
unknown's avatar
unknown committed
12196
    DBUG_RETURN(TRUE);
12197

unknown's avatar
unknown committed
12198
  cond->fix_fields(thd,(TABLE_LIST *) 0, (Item**)&cond);
unknown's avatar
unknown committed
12199 12200 12201 12202 12203 12204 12205 12206 12207 12208 12209
  if (join_tab->select)
  {
    error=(int) cond->add(join_tab->select->cond);
    join_tab->select_cond=join_tab->select->cond=cond;
  }
  else if ((join_tab->select=make_select(join_tab->table, 0, 0, cond,&error)))
    join_tab->select_cond=cond;

  DBUG_RETURN(error ? TRUE : FALSE);
}

12210 12211 12212 12213 12214 12215 12216 12217 12218 12219 12220 12221 12222 12223 12224 12225 12226

/*
  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
12227
/****************************************************************************
12228 12229 12230 12231 12232 12233 12234 12235 12236 12237 12238 12239 12240 12241 12242 12243 12244 12245 12246 12247 12248 12249 12250 12251 12252 12253
  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;

  if (!(rollup.fields= (List<Item>*) thd->alloc((sizeof(Item*) +
						 sizeof(List<Item>) +
						 ref_pointer_array_size)
						* send_group_parts)))
    return 1;
  rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
  ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts);
unknown's avatar
unknown committed
12254
  rollup.item_null= new (thd->mem_root) Item_null();
12255 12256 12257 12258 12259 12260 12261

  /*
    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++)
  {
12262 12263
    List<Item> *rollup_fields= &rollup.fields[i];
    rollup_fields->empty();
12264 12265 12266
    rollup.ref_pointer_arrays[i]= ref_array;
    ref_array+= all_fields.elements;
    for (j=0 ; j < fields_list.elements ; j++)
12267
      rollup_fields->push_back(rollup.item_null);
12268 12269 12270 12271 12272 12273 12274 12275 12276 12277
  }
  return 0;
}
  

/*
  Fill up rollup structures with pointers to fields to use

  SYNOPSIS
    rollup_make_fields()
12278 12279
    fields_arg			List of all fields (hidden and real ones)
    sel_fields			Pointer to selected fields
12280 12281 12282 12283 12284 12285 12286 12287 12288 12289 12290
    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
*/

12291
bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields,
12292 12293
			      Item_sum ***func)
{
12294 12295
  List_iterator_fast<Item> it(fields_arg);
  Item *first_field= sel_fields.head();
12296 12297 12298 12299 12300 12301 12302 12303 12304 12305 12306 12307 12308 12309 12310 12311 12312 12313 12314 12315 12316 12317 12318
  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
    ...
  */

12319
  for (level=0 ; level < send_group_parts ; level++)
12320 12321 12322 12323 12324 12325 12326 12327 12328 12329
  {
    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 */
12330
    Item **ref_array= ref_array_start + fields_arg.elements-1;
12331 12332 12333 12334 12335 12336 12337 12338 12339 12340 12341 12342 12343 12344 12345 12346 12347 12348 12349 12350 12351 12352 12353 12354 12355 12356 12357 12358 12359 12360 12361 12362 12363 12364 12365 12366 12367 12368 12369

    /* 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 */
12370 12371
	ORDER *group_tmp;
	for (group_tmp= start_group ; group_tmp ; group_tmp= group_tmp->next)
12372
	{
12373
	  if (*group_tmp->item == item)
12374 12375 12376 12377 12378 12379 12380 12381 12382 12383 12384 12385 12386 12387 12388 12389 12390 12391 12392 12393 12394 12395 12396 12397 12398 12399 12400 12401 12402 12403 12404 12405 12406 12407 12408 12409 12410 12411 12412 12413 12414 12415 12416 12417 12418 12419 12420 12421 12422 12423 12424 12425 12426 12427 12428 12429 12430 12431 12432 12433 12434 12435 12436 12437 12438 12439
	  {
	    /*
	      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
	    item= rollup.item_null;
	    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()))
    {
      if (send_records < unit->select_limit_cnt &&
	  result->send_data(rollup.fields[i]))
	return 1;
      send_records++;
    }
  }
  /* Restore ref_pointer_array */
  set_items_ref_array(current_ref_pointer_array);
  return 0;
}

12440 12441 12442 12443 12444 12445 12446 12447 12448 12449 12450 12451 12452 12453 12454 12455 12456 12457 12458 12459
/*
  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();
  }
}
12460

unknown's avatar
unknown committed
12461
/****************************************************************************
12462 12463
  EXPLAIN handling

12464
  Send a description about what how the select will be done to stdout
unknown's avatar
unknown committed
12465 12466
****************************************************************************/

unknown's avatar
unknown committed
12467
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
unknown's avatar
unknown committed
12468
			    bool distinct,const char *message)
unknown's avatar
unknown committed
12469 12470
{
  List<Item> field_list;
12471
  List<Item> item_list;
unknown's avatar
unknown committed
12472
  THD *thd=join->thd;
12473
  select_result *result=join->result;
12474
  Item *item_null= new Item_null();
unknown's avatar
af  
unknown committed
12475 12476
  CHARSET_INFO *cs= system_charset_info;
  int quick_type;
unknown's avatar
unknown committed
12477
  DBUG_ENTER("select_describe");
12478
  DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
unknown's avatar
unknown committed
12479
		      (ulong)join->select_lex, join->select_lex->type,
12480
		      message ? message : "NULL"));
12481
  /* Don't log this into the slow query log */
12482
  thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
unknown's avatar
unknown committed
12483
  join->unit->offset_limit_cnt= 0;
12484

unknown's avatar
unknown committed
12485
  if (message)
unknown's avatar
unknown committed
12486
  {
unknown's avatar
af  
unknown committed
12487 12488
    item_list.push_back(new Item_int((int32)
				     join->select_lex->select_number));
unknown's avatar
unknown committed
12489
    item_list.push_back(new Item_string(join->select_lex->type,
unknown's avatar
unknown committed
12490
					strlen(join->select_lex->type), cs));
12491
    for (uint i=0 ; i < 7; i++)
12492
      item_list.push_back(item_null);
unknown's avatar
unknown committed
12493
    item_list.push_back(new Item_string(message,strlen(message),cs));
12494
    if (result->send_data(item_list))
12495
      join->error= 1;
unknown's avatar
unknown committed
12496
  }
unknown's avatar
af  
unknown committed
12497 12498 12499 12500 12501 12502 12503 12504 12505 12506 12507 12508 12509 12510 12511 12512 12513 12514 12515 12516 12517 12518 12519 12520 12521 12522 12523 12524 12525 12526 12527 12528 12529 12530 12531 12532 12533 12534 12535 12536 12537 12538 12539 12540 12541 12542 12543 12544 12545 12546 12547 12548 12549 12550 12551 12552 12553 12554 12555 12556 12557 12558 12559 12560
  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
12561 12562 12563 12564
  else
  {
    table_map used_tables=0;
    for (uint i=0 ; i < join->tables ; i++)
unknown's avatar
unknown committed
12565
    {
unknown's avatar
unknown committed
12566 12567
      JOIN_TAB *tab=join->join_tab+i;
      TABLE *table=tab->table;
unknown's avatar
af  
unknown committed
12568
      char buff[512]; 
unknown's avatar
unknown committed
12569 12570
      char buff1[512], buff2[512], buff3[512];
      char keylen_str_buf[64];
unknown's avatar
af  
unknown committed
12571 12572
      String extra(buff, sizeof(buff),cs);
      char table_name_buffer[NAME_LEN];
unknown's avatar
unknown committed
12573 12574
      String tmp1(buff1,sizeof(buff1),cs);
      String tmp2(buff2,sizeof(buff2),cs);
unknown's avatar
unknown committed
12575
      String tmp3(buff3,sizeof(buff3),cs);
unknown's avatar
af  
unknown committed
12576
      extra.length(0);
12577 12578
      tmp1.length(0);
      tmp2.length(0);
unknown's avatar
unknown committed
12579
      tmp3.length(0);
12580

unknown's avatar
af  
unknown committed
12581
      quick_type= -1;
unknown's avatar
unknown committed
12582
      item_list.empty();
unknown's avatar
af  
unknown committed
12583 12584
      /* id */
      item_list.push_back(new Item_uint((uint32)
unknown's avatar
unknown committed
12585
				       join->select_lex->select_number));
unknown's avatar
af  
unknown committed
12586
      /* select_type */
unknown's avatar
unknown committed
12587 12588
      item_list.push_back(new Item_string(join->select_lex->type,
					  strlen(join->select_lex->type),
unknown's avatar
unknown committed
12589
					  cs));
unknown's avatar
unknown committed
12590
      if (tab->type == JT_ALL && tab->select && tab->select->quick)
unknown's avatar
unknown committed
12591
      {
unknown's avatar
af  
unknown committed
12592 12593 12594 12595
        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
12596 12597 12598 12599
          tab->type = JT_INDEX_MERGE;
        else
	  tab->type = JT_RANGE;
      }
unknown's avatar
af  
unknown committed
12600
      /* table */
unknown's avatar
unknown committed
12601
      if (table->derived_select_number)
unknown's avatar
unknown committed
12602
      {
unknown's avatar
unknown committed
12603
	/* Derived table name generation */
unknown's avatar
af  
unknown committed
12604
	int len= my_snprintf(table_name_buffer, sizeof(table_name_buffer)-1,
unknown's avatar
unknown committed
12605
			     "<derived%u>",
unknown's avatar
unknown committed
12606
			     table->derived_select_number);
unknown's avatar
af  
unknown committed
12607
	item_list.push_back(new Item_string(table_name_buffer, len, cs));
unknown's avatar
unknown committed
12608 12609 12610 12611
      }
      else
	item_list.push_back(new Item_string(table->table_name,
					    strlen(table->table_name),
unknown's avatar
unknown committed
12612
					    cs));
unknown's avatar
af  
unknown committed
12613
      /* type */
12614 12615
      item_list.push_back(new Item_string(join_type_str[tab->type],
					  strlen(join_type_str[tab->type]),
unknown's avatar
unknown committed
12616
					  cs));
unknown's avatar
unknown committed
12617
      uint j;
unknown's avatar
af  
unknown committed
12618
      /* Build "possible_keys" value and add it to item_list */
12619
      if (!tab->keys.is_clear_all())
unknown's avatar
unknown committed
12620
      {
unknown's avatar
unknown committed
12621
        for (j=0 ; j < table->keys ; j++)
12622 12623 12624 12625 12626
        {
          if (tab->keys.is_set(j))
          {
            if (tmp1.length())
              tmp1.append(',');
unknown's avatar
af  
unknown committed
12627 12628 12629
            tmp1.append(table->key_info[j].name, 
			strlen(table->key_info[j].name),
			system_charset_info);
12630 12631
          }
        }
unknown's avatar
unknown committed
12632
      }
12633
      if (tmp1.length())
unknown's avatar
unknown committed
12634
	item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),cs));
unknown's avatar
unknown committed
12635
      else
12636
	item_list.push_back(item_null);
unknown's avatar
af  
unknown committed
12637 12638

      /* Build "key", "key_len", and "ref" values and add them to item_list */
unknown's avatar
unknown committed
12639
      if (tab->ref.key_parts)
unknown's avatar
unknown committed
12640
      {
12641
	KEY *key_info=table->key_info+ tab->ref.key;
unknown's avatar
unknown committed
12642
        register uint length;
12643
	item_list.push_back(new Item_string(key_info->name,
12644 12645
					    strlen(key_info->name),
					    system_charset_info));
unknown's avatar
unknown committed
12646 12647 12648 12649
        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
12650 12651
	for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
	{
12652 12653
	  if (tmp2.length())
	    tmp2.append(',');
unknown's avatar
af  
unknown committed
12654 12655
	  tmp2.append((*ref)->name(), strlen((*ref)->name()),
		      system_charset_info);
unknown's avatar
unknown committed
12656
	}
unknown's avatar
unknown committed
12657
	item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
unknown's avatar
unknown committed
12658 12659 12660
      }
      else if (tab->type == JT_NEXT)
      {
12661
	KEY *key_info=table->key_info+ tab->index;
unknown's avatar
unknown committed
12662
        register uint length;
12663
	item_list.push_back(new Item_string(key_info->name,
unknown's avatar
unknown committed
12664
					    strlen(key_info->name),cs));
unknown's avatar
unknown committed
12665 12666 12667 12668 12669
        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));
12670
	item_list.push_back(item_null);
unknown's avatar
unknown committed
12671 12672 12673
      }
      else if (tab->select && tab->select->quick)
      {
unknown's avatar
af  
unknown committed
12674
        tab->select->quick->add_keys_and_lengths(&tmp2, &tmp3);
unknown's avatar
unknown committed
12675
	item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
unknown's avatar
af  
unknown committed
12676
	item_list.push_back(new Item_string(tmp3.ptr(),tmp3.length(),cs));
12677
	item_list.push_back(item_null);
unknown's avatar
unknown committed
12678 12679 12680
      }
      else
      {
12681 12682 12683
	item_list.push_back(item_null);
	item_list.push_back(item_null);
	item_list.push_back(item_null);
unknown's avatar
unknown committed
12684
      }
unknown's avatar
af  
unknown committed
12685
      /* Add "rows" field to item_list. */
12686 12687 12688
      item_list.push_back(new Item_int((longlong) (ulonglong)
				       join->best_positions[i]. records_read,
				       21));
unknown's avatar
af  
unknown committed
12689
      /* Build "Extra" field and add it to item_list. */
unknown's avatar
unknown committed
12690
      my_bool key_read=table->key_read;
unknown's avatar
af  
unknown committed
12691 12692
      if ((tab->type == JT_NEXT || tab->type == JT_CONST) &&
          table->used_keys.is_set(tab->index))
unknown's avatar
unknown committed
12693
	key_read=1;
unknown's avatar
af  
unknown committed
12694 12695 12696 12697
      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
12698
      if (tab->info)
unknown's avatar
unknown committed
12699
	item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs));
12700
      else
unknown's avatar
unknown committed
12701
      {
unknown's avatar
af  
unknown committed
12702 12703 12704 12705 12706 12707 12708
        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);
        }
12709
	if (tab->select)
unknown's avatar
unknown committed
12710
	{
12711 12712
	  if (tab->use_quick == 2)
	  {
12713
            char buf[MAX_KEY/8+1];
unknown's avatar
af  
unknown committed
12714 12715 12716
            extra.append("; Range checked for each record (index map: 0x");
            extra.append(tab->keys.print(buf));
            extra.append(')');
12717
	  }
12718
	  else if (tab->select->cond)
unknown's avatar
af  
unknown committed
12719
            extra.append("; Using where");
unknown's avatar
unknown committed
12720
	}
12721
	if (key_read)
12722 12723 12724 12725 12726 12727
        {
          if (quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)
            extra.append("; Using index for group-by");
          else
            extra.append("; Using index");
        }
12728
	if (table->reginfo.not_exists_optimize)
unknown's avatar
af  
unknown committed
12729
	  extra.append("; Not exists");
12730 12731 12732
	if (need_tmp_table)
	{
	  need_tmp_table=0;
unknown's avatar
af  
unknown committed
12733
	  extra.append("; Using temporary");
12734 12735 12736 12737
	}
	if (need_order)
	{
	  need_order=0;
unknown's avatar
af  
unknown committed
12738
	  extra.append("; Using filesort");
12739
	}
12740
	if (distinct & test_all_bits(used_tables,thd->used_tables))
unknown's avatar
af  
unknown committed
12741 12742 12743 12744 12745 12746 12747 12748 12749 12750 12751
	  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
12752 12753 12754
      }
      // For next iteration
      used_tables|=table->map;
12755
      if (result->send_data(item_list))
12756
	join->error= 1;
unknown's avatar
unknown committed
12757
    }
unknown's avatar
unknown committed
12758
  }
unknown's avatar
unknown committed
12759 12760 12761 12762 12763 12764 12765
  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
12766 12767 12768
  DBUG_VOID_RETURN;
}

12769

unknown's avatar
unknown committed
12770
bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
unknown's avatar
unknown committed
12771
{
unknown's avatar
unknown committed
12772
  DBUG_ENTER("mysql_explain_union");
unknown's avatar
unknown committed
12773
  bool res= 0;
unknown's avatar
unknown committed
12774
  SELECT_LEX *first= unit->first_select();
unknown's avatar
af  
unknown committed
12775

unknown's avatar
unknown committed
12776 12777 12778 12779
  for (SELECT_LEX *sl= first;
       sl;
       sl= sl->next_select())
  {
unknown's avatar
af  
unknown committed
12780 12781 12782 12783 12784 12785 12786 12787 12788 12789 12790 12791 12792 12793 12794 12795 12796 12797 12798 12799 12800 12801 12802 12803 12804 12805 12806 12807 12808 12809 12810 12811 12812 12813 12814 12815 12816 12817 12818 12819 12820 12821 12822
    // 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;
    if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
      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
12823
  }
unknown's avatar
unknown committed
12824
  DBUG_RETURN(res || thd->net.report_error);
unknown's avatar
unknown committed
12825 12826
}

12827

12828 12829 12830 12831 12832 12833
/*
  Print joins from the FROM clause

  SYNOPSIS
    print_join()
    thd     thread handler
12834
    str     string where table should be printed
12835 12836 12837 12838 12839 12840 12841 12842 12843 12844 12845 12846 12847 12848 12849 12850
    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
12851
  (*table)->print(thd, str);
12852 12853 12854 12855 12856

  TABLE_LIST **end= table + tables->elements;
  for(TABLE_LIST **tbl= table + 1; tbl < end; tbl++)
  {
    TABLE_LIST *curr= *tbl;
unknown's avatar
unknown committed
12857 12858
    if (curr->outer_join)
      str->append(" left join ", 11); // MySQL converg right to left joins
12859 12860 12861 12862 12863 12864 12865 12866 12867 12868 12869 12870 12871 12872 12873 12874 12875 12876 12877 12878 12879 12880 12881 12882 12883 12884 12885 12886 12887 12888 12889
    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(')');
  }
12890
  else
unknown's avatar
VIEW  
unknown committed
12891
  {
12892 12893
    const char *cmp_name;                         // Name to compare with alias
    if (view_name.str)
unknown's avatar
VIEW  
unknown committed
12894
    {
12895 12896 12897 12898
      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
12899
    }
12900 12901 12902 12903 12904 12905 12906 12907 12908 12909 12910
    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('.');
12911 12912
      if (schema_table)
      {
unknown's avatar
unknown committed
12913 12914 12915
        append_identifier(thd, str, schema_table_name,
                          strlen(schema_table_name));
        cmp_name= schema_table_name;
12916 12917 12918 12919 12920 12921
      }
      else
      {
        append_identifier(thd, str, real_name, real_name_length);
        cmp_name= real_name;
      }
12922 12923
    }
    if (my_strcasecmp(table_alias_charset, cmp_name, alias))
12924 12925
    {
      str->append(' ');
12926
      append_identifier(thd, str, alias, strlen(alias));
12927 12928 12929 12930
    }
  }
}

12931

unknown's avatar
unknown committed
12932 12933 12934 12935 12936
void st_select_lex::print(THD *thd, String *str)
{
  if (!thd)
    thd= current_thd;

12937
  str->append("select ", 7);
12938

12939
  /* First add options */
unknown's avatar
unknown committed
12940
  if (options & SELECT_STRAIGHT_JOIN)
12941
    str->append("straight_join ", 14);
unknown's avatar
af  
unknown committed
12942
  if ((thd->lex->lock_option == TL_READ_HIGH_PRIORITY) &&
unknown's avatar
unknown committed
12943
      (this == &thd->lex->select_lex))
12944
    str->append("high_priority ", 14);
unknown's avatar
unknown committed
12945
  if (options & SELECT_DISTINCT)
12946
    str->append("distinct ", 9);
unknown's avatar
unknown committed
12947
  if (options & SELECT_SMALL_RESULT)
unknown's avatar
af  
unknown committed
12948
    str->append("sql_small_result ", 17);
unknown's avatar
unknown committed
12949
  if (options & SELECT_BIG_RESULT)
unknown's avatar
af  
unknown committed
12950
    str->append("sql_big_result ", 15);
unknown's avatar
unknown committed
12951
  if (options & OPTION_BUFFER_RESULT)
unknown's avatar
af  
unknown committed
12952
    str->append("sql_buffer_result ", 18);
unknown's avatar
unknown committed
12953
  if (options & OPTION_FOUND_ROWS)
unknown's avatar
af  
unknown committed
12954
    str->append("sql_calc_found_rows ", 20);
unknown's avatar
unknown committed
12955
  if (!thd->lex->safe_to_cache_query)
unknown's avatar
af  
unknown committed
12956
    str->append("sql_no_cache ", 13);
unknown's avatar
unknown committed
12957
  if (options & OPTION_TO_QUERY_CACHE)
unknown's avatar
af  
unknown committed
12958
    str->append("sql_cache ", 10);
unknown's avatar
unknown committed
12959 12960 12961 12962 12963 12964 12965 12966 12967 12968 12969 12970 12971 12972 12973 12974 12975 12976 12977 12978

  //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)
  {
12979
    str->append(" from ", 6);
12980 12981
    /* go through join tree */
    print_join(thd, str, &top_join_list);
unknown's avatar
unknown committed
12982 12983
  }

12984 12985
  // Where
  Item *cur_where= where;
unknown's avatar
unknown committed
12986
  if (join)
12987 12988
    cur_where= join->conds;
  if (cur_where)
unknown's avatar
unknown committed
12989
  {
12990
    str->append(" where ", 7);
12991
    cur_where->print(str);
unknown's avatar
unknown committed
12992 12993
  }

12994
  // group by & olap
unknown's avatar
unknown committed
12995 12996
  if (group_list.elements)
  {
12997
    str->append(" group by ", 10);
unknown's avatar
unknown committed
12998 12999 13000 13001
    print_order(str, (ORDER *) group_list.first);
    switch (olap)
    {
      case CUBE_TYPE:
13002
	str->append(" with cube", 10);
unknown's avatar
unknown committed
13003 13004
	break;
      case ROLLUP_TYPE:
13005
	str->append(" with rollup", 12);
unknown's avatar
unknown committed
13006 13007 13008 13009 13010 13011
	break;
      default:
	;  //satisfy compiler
    }
  }

13012 13013
  // having
  Item *cur_having= having;
unknown's avatar
unknown committed
13014
  if (join)
13015
    cur_having= join->having;
unknown's avatar
unknown committed
13016

13017
  if (cur_having)
unknown's avatar
unknown committed
13018
  {
13019
    str->append(" having ", 8);
13020
    cur_having->print(str);
unknown's avatar
unknown committed
13021 13022 13023 13024
  }

  if (order_list.elements)
  {
13025
    str->append(" order by ", 10);
unknown's avatar
unknown committed
13026 13027 13028 13029 13030 13031 13032 13033
    print_order(str, (ORDER *) order_list.first);
  }

  // limit
  print_limit(thd, str);

  // PROCEDURE unsupported here
}
unknown's avatar
af  
unknown committed
13034 13035 13036 13037 13038 13039 13040 13041 13042 13043


/*
  change select_result object of JOIN

  SYNOPSIS
    JOIN::change_result()
    res		new select_result object

  RETURN
unknown's avatar
unknown committed
13044 13045
    FALSE - OK
    TRUE  - error
unknown's avatar
af  
unknown committed
13046 13047
*/

unknown's avatar
unknown committed
13048
bool JOIN::change_result(select_result *res)
unknown's avatar
af  
unknown committed
13049 13050 13051 13052 13053
{
  DBUG_ENTER("JOIN::change_result");
  result= res;
  if (!procedure && result->prepare(fields_list, select_lex->master_unit()))
  {
unknown's avatar
unknown committed
13054
    DBUG_RETURN(TRUE);
unknown's avatar
af  
unknown committed
13055
  }
unknown's avatar
unknown committed
13056
  DBUG_RETURN(FALSE);
unknown's avatar
af  
unknown committed
13057
}