sql_select.cc 271 KB
Newer Older
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"
34
};
unknown's avatar
unknown committed
35

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

39
static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
unknown's avatar
unknown committed
40
static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
unknown's avatar
unknown committed
41
				 DYNAMIC_ARRAY *keyuse);
42 43
static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
				JOIN_TAB *join_tab,
44 45
                                uint tables, COND *conds,
				table_map table_map, SELECT_LEX *select_lex);
unknown's avatar
unknown committed
46 47
static int sort_keyuse(KEYUSE *a,KEYUSE *b);
static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key);
48 49
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
			       table_map used_tables);
unknown's avatar
unknown committed
50 51 52 53 54 55
static void find_best_combination(JOIN *join,table_map rest_tables);
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
56 57
static store_key *get_store_key(THD *thd,
				KEYUSE *keyuse, table_map used_tables,
unknown's avatar
unknown committed
58 59 60 61 62
				KEY_PART_INFO *key_part, char *key_buff,
				uint maybe_null);
static bool make_simple_join(JOIN *join,TABLE *tmp_table);
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
static void make_join_readinfo(JOIN *join,uint options);
63
static bool only_eq_ref_tables(JOIN *join, ORDER *order, table_map tables);
unknown's avatar
unknown committed
64 65 66 67
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);
68
static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
unknown's avatar
unknown committed
69 70
			    List<Item> &fields, bool send_row,
			    uint select_options, const char *info,
71 72
			    Item *having, Procedure *proc,
			    SELECT_LEX_UNIT *unit);
73 74 75 76
static COND *optimize_cond(THD *thd, COND *conds,
			   Item::cond_result *cond_value);
static COND *remove_eq_conds(THD *thd, COND *cond, 
			     Item::cond_result *cond_value);
unknown's avatar
unknown committed
77 78 79
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,
80
				    ulong options);
unknown's avatar
unknown committed
81 82 83 84
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);
85
static int flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last);
unknown's avatar
unknown committed
86 87 88 89 90 91 92 93 94
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);
95
static int join_read_const_table(JOIN_TAB *tab, POSITION *pos);
unknown's avatar
unknown committed
96 97 98 99
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);
100
static int join_read_last_key(JOIN_TAB *tab);
unknown's avatar
unknown committed
101 102 103 104 105
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);
106 107 108 109 110 111
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
112 113
static int join_ft_read_first(JOIN_TAB *tab);
static int join_ft_read_next(READ_RECORD *info);
114 115
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
116 117 118
static COND *make_cond_for_table(COND *cond,table_map table,
				 table_map used_table);
static Item* part_of_refkey(TABLE *form,Field *field);
unknown's avatar
unknown committed
119
static uint find_shortest_key(TABLE *table, const key_map *usable_keys);
unknown's avatar
unknown committed
120
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
121
				    ha_rows select_limit, bool no_changes);
122
static int create_sort_index(THD *thd, JOIN *join, ORDER *order,
unknown's avatar
unknown committed
123
			     ha_rows filesort_limit, ha_rows select_limit);
124 125
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
			     Item *having);
unknown's avatar
unknown committed
126
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
127
				   ulong offset,Item *having);
unknown's avatar
unknown committed
128
static int remove_dup_with_hash_index(THD *thd,TABLE *table,
unknown's avatar
unknown committed
129
				      uint field_count, Field **first_field,
130
				      ulong key_length,Item *having);
unknown's avatar
unknown committed
131 132 133
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);
134 135
static void reset_cache_read(JOIN_CACHE *cache);
static void reset_cache_write(JOIN_CACHE *cache);
unknown's avatar
unknown committed
136 137 138 139
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);
140 141 142
static ORDER *create_distinct_group(THD *thd, ORDER *order,
				    List<Item> &fields,
				    bool *all_order_by_fields_used);
unknown's avatar
unknown committed
143 144 145
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);
146
static bool make_group_fields(JOIN *main_join, JOIN *curr_join);
unknown's avatar
unknown committed
147
static bool alloc_group_fields(JOIN *join,ORDER *group);
148
// Create list for using with tempory table
149
static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
150 151 152 153 154 155 156 157
				     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
158 159 160 161
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);
162
static bool init_sum_functions(Item_sum **func, Item_sum **end);
unknown's avatar
unknown committed
163
static bool update_sum_func(Item_sum **func);
164
static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
unknown's avatar
unknown committed
165
			    bool distinct, const char *message=NullS);
166
static Item *remove_additional_cond(Item* conds);
unknown's avatar
unknown committed
167

168

169 170 171 172 173 174 175 176
/*
  This handles SELECT with and without UNION
*/

int handle_select(THD *thd, LEX *lex, select_result *result)
{
  int res;
  register SELECT_LEX *select_lex = &lex->select_lex;
177 178
  DBUG_ENTER("handle_select");

unknown's avatar
unknown committed
179
  if (select_lex->next_select())
180
    res=mysql_union(thd, lex, result, &lex->unit);
181
  else
182 183 184 185 186 187 188 189 190 191 192
    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,
193
		      result, &(lex->unit), &(lex->select_lex));
194

195 196 197
  /* Don't set res if it's -1 as we may want this later */
  DBUG_PRINT("info",("res: %d  report_error: %d", res,
		     thd->net.report_error));
198
  if (thd->net.report_error || res<0)
199
  {
200 201
    result->send_error(0, NullS);
    result->abort();
202
    res= 1;					// Error sent to client
unknown's avatar
unknown committed
203
  }
204
  DBUG_RETURN(res);
205 206
}

207

208
/*
209
  Function to setup clauses without sum functions
210
*/
211 212
inline int setup_without_group(THD *thd, Item **ref_pointer_array,
			       TABLE_LIST *tables,
213 214 215 216 217 218
			       List<Item> &fields,
			       List<Item> &all_fields,
			       COND **conds,
			       ORDER *order,
			       ORDER *group, bool *hidden_group_fields)
{
unknown's avatar
unknown committed
219 220 221 222 223
  bool save_allow_sum_func;
  int res;
  DBUG_ENTER("setup_without_group");

  save_allow_sum_func= thd->allow_sum_func;
224
  thd->allow_sum_func= 0;
unknown's avatar
unknown committed
225 226 227 228 229
  res= (setup_conds(thd, tables, conds) ||
        setup_order(thd, ref_pointer_array, tables, fields, all_fields,
                    order) ||
        setup_group(thd, ref_pointer_array, tables, fields, all_fields,
                    group, hidden_group_fields));
230
  thd->allow_sum_func= save_allow_sum_func;
unknown's avatar
unknown committed
231
  DBUG_RETURN(res);
232 233
}

unknown's avatar
unknown committed
234
/*****************************************************************************
235 236
  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
237 238
*****************************************************************************/

239
/*
unknown's avatar
unknown committed
240
  Prepare of whole select (including sub queries in future).
241 242 243
  return -1 on error
          0 on success
*/
unknown's avatar
unknown committed
244
int
245 246 247 248
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
249
	      Item *having_init,
250 251
	      ORDER *proc_param_init, SELECT_LEX *select_lex_arg,
	      SELECT_LEX_UNIT *unit_arg)
unknown's avatar
unknown committed
252
{
253
  DBUG_ENTER("JOIN::prepare");
unknown's avatar
unknown committed
254

255 256 257 258
  // to prevent double initialization on EXPLAIN
  if (optimized)
    DBUG_RETURN(0);

259 260 261 262 263 264
  conds= conds_init;
  order= order_init;
  group_list= group_init;
  having= having_init;
  proc_param= proc_param_init;
  tables_list= tables_init;
265
  select_lex= select_lex_arg;
266
  select_lex->join= this;
267
  union_part= (unit_arg->first_select()->next_select() != 0);
unknown's avatar
unknown committed
268 269 270

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

271
  if (setup_tables(tables_list) ||
272
      setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
unknown's avatar
unknown committed
273
      select_lex->setup_ref_array(thd, og_num) ||
274 275 276 277 278
      setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
		   &all_fields, 1) ||
      setup_without_group(thd, (*rref_pointer_array), tables_list, fields_list,
			  all_fields, &conds, order, group_list, 
			  &hidden_group_fields))
unknown's avatar
unknown committed
279 280
    DBUG_RETURN(-1);				/* purecov: inspected */

281
  ref_pointer_array= *rref_pointer_array;
282
  
unknown's avatar
unknown committed
283 284 285 286
  if (having)
  {
    thd->where="having clause";
    thd->allow_sum_func=1;
unknown's avatar
unknown committed
287
    select_lex->having_fix_field= 1;
unknown's avatar
unknown committed
288 289 290
    bool having_fix_rc= (!having->fixed &&
			 (having->fix_fields(thd, tables_list, &having) ||
			  having->check_cols(1)));
unknown's avatar
unknown committed
291
    select_lex->having_fix_field= 0;
unknown's avatar
unknown committed
292
    if (having_fix_rc || thd->net.report_error)
unknown's avatar
unknown committed
293 294
      DBUG_RETURN(-1);				/* purecov: inspected */
    if (having->with_sum_func)
295
      having->split_sum_func(thd, ref_pointer_array, all_fields);
unknown's avatar
unknown committed
296
  }
297

298 299 300
  // Is it subselect
  {
    Item_subselect *subselect;
unknown's avatar
unknown committed
301
    if ((subselect= select_lex->master_unit()->item))
302 303
    {
      Item_subselect::trans_res res;
unknown's avatar
unknown committed
304
      if ((res= subselect->select_transformer(this)) !=
305 306
	  Item_subselect::RES_OK)
	DBUG_RETURN((res == Item_subselect::RES_ERROR));
307 308 309
    }
  }

310
  if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
unknown's avatar
unknown committed
311
    DBUG_RETURN(-1);
312 313
  

unknown's avatar
unknown committed
314 315 316 317 318
  /*
    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;
319
  */
unknown's avatar
unknown committed
320
  {
321
    if (!group_list)
unknown's avatar
unknown committed
322 323
    {
      uint flag=0;
324
      List_iterator_fast<Item> it(fields_list);
unknown's avatar
unknown committed
325 326 327 328 329
      Item *item;
      while ((item= it++))
      {
	if (item->with_sum_func)
	  flag|=1;
unknown's avatar
unknown committed
330
	else if (!(flag & 2) && !item->const_during_execution())
unknown's avatar
unknown committed
331 332 333 334 335 336 337 338
	  flag|=2;
      }
      if (flag == 3)
      {
	my_error(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,MYF(0));
	DBUG_RETURN(-1);
      }
    }
339 340
    TABLE_LIST *table_ptr;
    for (table_ptr= tables_list ; table_ptr ; table_ptr= table_ptr->next)
341
      tables++;
unknown's avatar
unknown committed
342
  }
343 344 345
  {
    /* Caclulate the number of groups */
    send_group_parts= 0;
346
    for (ORDER *group_tmp= group_list ; group_tmp ; group_tmp= group_tmp->next)
347 348 349
      send_group_parts++;
  }
  
350
  procedure= setup_procedure(thd, proc_param, result, fields_list, &error);
unknown's avatar
unknown committed
351
  if (error)
352
    goto err;					/* purecov: inspected */
unknown's avatar
unknown committed
353 354
  if (procedure)
  {
355 356
    if (setup_new_fields(thd, tables_list, fields_list, all_fields,
			 procedure->param_fields))
357
	goto err;				/* purecov: inspected */
unknown's avatar
unknown committed
358 359
    if (procedure->group)
    {
360
      if (!test_if_subpart(procedure->group,group_list))
unknown's avatar
unknown committed
361 362 363
      {						/* purecov: inspected */
	my_message(0,"Can't handle procedures with differents groups yet",
		   MYF(0));			/* purecov: inspected */
364
	goto err;				/* purecov: inspected */
unknown's avatar
unknown committed
365 366 367
      }
    }
#ifdef NOT_NEEDED
368
    else if (!group_list && procedure->flags & PROC_GROUP)
unknown's avatar
unknown committed
369 370
    {
      my_message(0,"Select must have a group with this procedure",MYF(0));
371
      goto err;
unknown's avatar
unknown committed
372 373 374
    }
#endif
    if (order && (procedure->flags & PROC_NO_SORT))
375
    {						/* purecov: inspected */
unknown's avatar
unknown committed
376
      my_message(0,"Can't use order with this procedure",MYF(0)); /* purecov: inspected */
377
      goto err;					/* purecov: inspected */
unknown's avatar
unknown committed
378 379 380 381
    }
  }

  /* Init join struct */
382
  count_field_types(&tmp_table_param, all_fields, 0);
383
  ref_pointer_array_size= all_fields.elements*sizeof(Item*);
384 385
  this->group= group_list != 0;
  row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
386
	      unit_arg->select_limit_cnt);
unknown's avatar
unknown committed
387
  /* select_limit is used to decide if we are likely to scan the whole table */
388
  select_limit= unit_arg->select_limit_cnt;
unknown's avatar
unknown committed
389 390
  if (having || (select_options & OPTION_FOUND_ROWS))
    select_limit= HA_POS_ERROR;
391 392
  do_send_rows = (unit_arg->select_limit_cnt) ? 1 : 0;
  unit= unit_arg;
unknown's avatar
unknown committed
393 394

#ifdef RESTRICTED_GROUP
395
  if (sum_func_count && !group_list && (func_count || field_count))
unknown's avatar
unknown committed
396
  {
unknown's avatar
unknown committed
397
    my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0));
398
    goto err;
unknown's avatar
unknown committed
399 400
  }
#endif
401 402 403 404 405 406 407 408 409 410
  /*
    We must not yet prepare the result table if it is the same as one of the 
    source tables (INSERT SELECT). This is checked in mysql_execute_command()
    and OPTION_BUFFER_RESULT is added to the select_options. A temporary 
    table is then used to hold the result. The preparation may disable 
    indexes on the result table, which may be used during the select, if it
    is the same table (Bug #6034). Do the preparation after the select phase.
  */
  if (! procedure && ! test(select_options & OPTION_BUFFER_RESULT) &&
      result && result->prepare(fields_list, unit_arg))
411 412 413 414 415 416 417
    goto err;					/* purecov: inspected */

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

418
  DBUG_RETURN(0); // All OK
419 420 421 422 423

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

426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
/*
  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 &&
442
      ((Item_func *)this->conds)->functype() == Item_func::EQ_FUNC &&
443 444 445 446 447 448 449 450 451 452 453
      ((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)
  {
454 455 456 457
    if ((*where= remove_additional_cond(conds)))
      join_tab->info= "Using index; Using where";
    else
      join_tab->info= "Using index";
458 459 460 461 462 463
    return 1;
  }
  return 0;
}


464 465 466
/*
  global select optimisation.
  return 0 - success
467
         1 - error
468 469 470 471 472 473
  error code saved in field 'error'
*/
int
JOIN::optimize()
{
  DBUG_ENTER("JOIN::optimize");
unknown's avatar
unknown committed
474
  // to prevent double initialization on EXPLAIN
475 476 477
  if (optimized)
    DBUG_RETURN(0);
  optimized= 1;
unknown's avatar
unknown committed
478

479
  // Ignore errors of execution if option IGNORE present
480
  if (thd->lex->ignore)
481
    thd->lex->current_select->no_error= 1;
unknown's avatar
unknown committed
482 483
#ifdef HAVE_REF_TO_FIELDS			// Not done yet
  /* Add HAVING to WHERE if possible */
484
  if (having && !group_list && !sum_func_count)
unknown's avatar
unknown committed
485 486 487
  {
    if (!conds)
    {
488 489
      conds= having;
      having= 0;
unknown's avatar
unknown committed
490 491 492
    }
    else if ((conds=new Item_cond_and(conds,having)))
    {
unknown's avatar
unknown committed
493
      conds->fix_fields(thd, tables_list, &conds);
494
      conds->change_ref_to_fields(thd, tables_list);
495
      conds->top_level_item();
496
      having= 0;
unknown's avatar
unknown committed
497 498 499 500
    }
  }
#endif

unknown's avatar
unknown committed
501
  conds= optimize_cond(thd, conds, &cond_value);
502
  if (thd->net.report_error)
unknown's avatar
unknown committed
503
  {
unknown's avatar
unknown committed
504
    error= 1;
505
    DBUG_PRINT("error",("Error from optimize_cond"));
506
    DBUG_RETURN(1);
unknown's avatar
unknown committed
507
  }
unknown's avatar
unknown committed
508

unknown's avatar
unknown committed
509 510
  if (cond_value == Item::COND_FALSE ||
      (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
unknown's avatar
unknown committed
511
  {						/* Impossible cond */
512
    zero_result_cause= "Impossible WHERE";
513
    error= 0;
514
    DBUG_RETURN(0);
unknown's avatar
unknown committed
515 516 517
  }

  /* Optimize count(*), min() and max() */
518
  if (tables_list && tmp_table_param.sum_func_count && ! group_list)
unknown's avatar
unknown committed
519 520
  {
    int res;
unknown's avatar
unknown committed
521
    /*
unknown's avatar
unknown committed
522 523
      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
524
    */
525
    if ((res=opt_sum_query(tables_list, all_fields, conds)))
unknown's avatar
unknown committed
526
    {
unknown's avatar
unknown committed
527 528
      if (res > 1)
      {
529
	DBUG_RETURN(1);
unknown's avatar
unknown committed
530
      }
unknown's avatar
unknown committed
531 532
      if (res < 0)
      {
533
	zero_result_cause= "No matching min/max row";
unknown's avatar
unknown committed
534
	error=0;
535
	DBUG_RETURN(0);
unknown's avatar
unknown committed
536
      }
unknown's avatar
unknown committed
537
      zero_result_cause= "Select tables optimized away";
unknown's avatar
unknown committed
538
      tables_list= 0;				// All tables resolved
unknown's avatar
unknown committed
539 540
    }
  }
541
  if (!tables_list)
542 543
  {
    error= 0;
544
    DBUG_RETURN(0);
545
  }
unknown's avatar
unknown committed
546
  error= -1;					// Error is sent to client
547
  sort_by_table= get_sort_by_table(order, group_list, tables_list);
unknown's avatar
unknown committed
548 549

  /* Calculate how to do the join */
550 551
  thd->proc_info= "statistics";
  if (make_join_statistics(this, tables_list, conds, &keyuse) ||
552
      thd->is_fatal_error)
553 554
  {
    DBUG_PRINT("error",("Error: make_join_statistics() failed"));
unknown's avatar
unknown committed
555
    DBUG_RETURN(1);
556
  }
557

unknown's avatar
unknown committed
558 559
  /* Remove distinct if only const tables */
  select_distinct= select_distinct && (const_tables != tables);
560
  thd->proc_info= "preparing";
unknown's avatar
unknown committed
561
  if (result->initialize_tables(this))
unknown's avatar
unknown committed
562
  {
563 564
    DBUG_PRINT("error",("Error: initialize_tables() failed"));
    DBUG_RETURN(1);				// error == -1
unknown's avatar
unknown committed
565
  }
566
  if (const_table_map != found_const_table_map &&
567
      !(select_options & SELECT_DESCRIBE) &&
unknown's avatar
unknown committed
568 569 570
      (!conds ||
       !(conds->used_tables() & RAND_TABLE_BIT) ||
       select_lex->master_unit() == &thd->lex->unit)) // upper level SELECT
unknown's avatar
unknown committed
571
  {
unknown's avatar
unknown committed
572
    zero_result_cause= "no matching row in const table";
573 574
    DBUG_PRINT("error",("Error: %s", zero_result_cause));
    error= 0;
575
    DBUG_RETURN(0);
unknown's avatar
unknown committed
576 577
  }
  if (!(thd->options & OPTION_BIG_SELECTS) &&
unknown's avatar
unknown committed
578
      best_read > (double) thd->variables.max_join_size &&
unknown's avatar
unknown committed
579 580
      !(select_options & SELECT_DESCRIBE))
  {						/* purecov: inspected */
581
    my_message(ER_TOO_BIG_SELECT, ER(ER_TOO_BIG_SELECT), MYF(0));
unknown's avatar
unknown committed
582
    error= 1;					/* purecov: inspected */
unknown's avatar
unknown committed
583
    DBUG_RETURN(1);
unknown's avatar
unknown committed
584
  }
585
  if (const_tables && !thd->locked_tables &&
unknown's avatar
unknown committed
586
      !(select_options & SELECT_NO_UNLOCK))
587
    mysql_unlock_some_tables(thd, table, const_tables);
unknown's avatar
unknown committed
588

589
  if (!conds && outer_join)
590 591 592 593
  {
    /* Handle the case where we have an OUTER JOIN without a WHERE */
    conds=new Item_int((longlong) 1,1);	// Always true
  }
594 595
  select=make_select(*table, const_table_map,
		     const_table_map, conds, &error);
unknown's avatar
unknown committed
596
  if (error)
unknown's avatar
unknown committed
597 598
  {						/* purecov: inspected */
    error= -1;					/* purecov: inspected */
599
    DBUG_PRINT("error",("Error: make_select() failed"));
unknown's avatar
unknown committed
600
    DBUG_RETURN(1);
unknown's avatar
unknown committed
601
  }
602
  if (make_join_select(this, select, conds))
unknown's avatar
unknown committed
603
  {
604 605
    zero_result_cause=
      "Impossible WHERE noticed after reading const tables";
606
    DBUG_RETURN(0);				// error == 0
unknown's avatar
unknown committed
607 608 609 610 611
  }

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

  /* Optimize distinct away if possible */
unknown's avatar
unknown committed
612 613
  {
    ORDER *org_order= order;
unknown's avatar
unknown committed
614
    order=remove_const(this, order,conds,&simple_order);
unknown's avatar
unknown committed
615 616 617 618 619 620 621
    /*
      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;
  }
622
  if (group_list || tmp_table_param.sum_func_count)
unknown's avatar
unknown committed
623 624 625 626
  {
    if (! hidden_group_fields)
      select_distinct=0;
  }
unknown's avatar
unknown committed
627
  else if (select_distinct && tables - const_tables == 1)
unknown's avatar
unknown committed
628
  {
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
    /*
      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
644
    JOIN_TAB *tab= &join_tab[const_tables];
645 646 647
    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
648 649
    if ((group_list=create_distinct_group(thd, order, fields_list,
				          &all_order_fields_used)))
650 651
    {
      bool skip_group= (skip_sort_order &&
unknown's avatar
unknown committed
652
			test_if_skip_sort_order(tab, group_list, select_limit,
653 654 655 656 657 658 659 660 661
						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)
662 663 664 665 666 667
	{
	  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
668
	    */
unknown's avatar
unknown committed
669
	    tmp_table_param.quick_group=0;
670
	  }
671
	  order=0;
unknown's avatar
unknown committed
672
        }
unknown's avatar
unknown committed
673
	group=1;				// For end_write_group
674 675
      }
      else
unknown's avatar
unknown committed
676
	group_list= 0;
unknown's avatar
unknown committed
677
    }
678
    else if (thd->is_fatal_error)			// End of memory
unknown's avatar
unknown committed
679
      DBUG_RETURN(1);
unknown's avatar
unknown committed
680
  }
681 682 683
  simple_group= 0;
  if (rollup.state == ROLLUP::STATE_NONE)
    group_list= remove_const(this, group_list, conds, &simple_group);
684
  if (!group_list && group)
unknown's avatar
unknown committed
685 686 687 688 689
  {
    order=0;					// The output has only one row
    simple_order=1;
  }

690 691
  calc_group_buffer(this, group_list);
  send_group_parts= tmp_table_param.group_parts; /* Save org parts */
unknown's avatar
unknown committed
692 693
  if (procedure && procedure->group)
  {
694 695 696
    group_list= procedure->group= remove_const(this, procedure->group, conds,
					       &simple_group);
    calc_group_buffer(this, group_list);
unknown's avatar
unknown committed
697 698
  }

699 700
  if (test_if_subpart(group_list, order) ||
      (!group_list && tmp_table_param.sum_func_count))
unknown's avatar
unknown committed
701 702
    order=0;

unknown's avatar
unknown committed
703
  // Can't use sort on head table if using row cache
704
  if (full_join)
unknown's avatar
unknown committed
705
  {
706
    if (group_list)
unknown's avatar
unknown committed
707 708 709 710 711
      simple_group=0;
    if (order)
      simple_order=0;
  }

712 713 714 715 716 717 718 719 720
  /*
    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.
  */
721
  need_tmp= (const_tables != tables &&
unknown's avatar
unknown committed
722
	     ((select_distinct || !simple_order || !simple_group) ||
unknown's avatar
unknown committed
723
	      (group_list && order) ||
724
	      test(select_options & OPTION_BUFFER_RESULT)));
unknown's avatar
unknown committed
725

unknown's avatar
unknown committed
726
  // No cache for MATCH
727
  make_join_readinfo(this,
unknown's avatar
unknown committed
728
		     (select_options & (SELECT_DESCRIBE |
729
					SELECT_NO_JOIN_CACHE)) |
unknown's avatar
unknown committed
730
		     (select_lex->ftfunc_list->elements ?
731
		      SELECT_NO_JOIN_CACHE : 0));
unknown's avatar
unknown committed
732

unknown's avatar
unknown committed
733 734 735 736
  /* Perform FULLTEXT search before all regular searches */
  if (!(select_options & SELECT_DESCRIBE))
    init_ftfuncs(thd, select_lex, test(order));

737 738 739
  /*
    is this simple IN subquery?
  */
740
  if (!group_list && !order &&
741
      unit->item && unit->item->substype() == Item_subselect::IN_SUBS &&
742
      tables == 1 && conds &&
743 744
      !unit->first_select()->next_select())
  {
745
    if (!having)
746
    {
747
      Item *where= 0;
748 749
      if (join_tab[0].type == JT_EQ_REF &&
	  join_tab[0].ref.items[0]->name == in_left_expr_name)
750
      {
751 752
	if (test_in_subselect(&where))
	{
753
	  join_tab[0].type= JT_UNIQUE_SUBQUERY;
754 755
	  error= 0;
	  DBUG_RETURN(unit->item->
756 757 758 759 760
		      change_engine(new
				    subselect_uniquesubquery_engine(thd,
								    join_tab,
								    unit->item,
								    where)));
761
	}
762
      }
763 764
      else if (join_tab[0].type == JT_REF &&
	       join_tab[0].ref.items[0]->name == in_left_expr_name)
765
      {
766 767
	if (test_in_subselect(&where))
	{
768
	  join_tab[0].type= JT_INDEX_SUBQUERY;
769 770
	  error= 0;
	  DBUG_RETURN(unit->item->
771 772 773 774 775 776
		      change_engine(new
				    subselect_indexsubquery_engine(thd,
								   join_tab,
								   unit->item,
								   where,
								   0)));
777
	}
778
      }
779
    } else if (join_tab[0].type == JT_REF_OR_NULL &&
780
	       join_tab[0].ref.items[0]->name == in_left_expr_name &&
781 782 783 784
	       having->type() == Item::FUNC_ITEM &&
	       ((Item_func *) having)->functype() ==
	       Item_func::ISNOTNULLTEST_FUNC)
    {
785
      join_tab[0].type= JT_INDEX_SUBQUERY;
786
      error= 0;
787 788 789 790 791

      if ((conds= remove_additional_cond(conds)))
	join_tab->info= "Using index; Using where";
      else
	join_tab->info= "Using index";
unknown's avatar
unknown committed
792

793
      DBUG_RETURN(unit->item->
794 795 796 797 798
		  change_engine(new subselect_indexsubquery_engine(thd,
								   join_tab,
								   unit->item,
								   conds,
								   1)));
799
    }
800

801
  }
802 803 804 805 806 807 808
  /*
    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
809 810

#ifdef HAVE_INNOBASE_DB
811
  if (need_tmp || select_distinct || group_list || order)
unknown's avatar
unknown committed
812
  {
813
    for (uint i_h = const_tables; i_h < tables; i_h++)
unknown's avatar
unknown committed
814
    {
815
      TABLE* table_h = join_tab[i_h].table;
unknown's avatar
unknown committed
816
      table_h->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
unknown's avatar
unknown committed
817 818 819 820
    }
  }
#endif

821
  DBUG_EXECUTE("info",TEST_join(this););
unknown's avatar
unknown committed
822 823 824 825 826
  /*
    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.
827
  */
828
  if (const_tables != tables &&
829
      (order || group_list) &&
830
      join_tab[const_tables].type != JT_ALL &&
831
      join_tab[const_tables].type != JT_FT &&
832
      join_tab[const_tables].type != JT_REF_OR_NULL &&
833
      (order && simple_order || group_list && simple_group))
unknown's avatar
unknown committed
834
  {
835
    if (add_ref_to_table_cond(thd,&join_tab[const_tables]))
unknown's avatar
unknown committed
836
      DBUG_RETURN(1);
unknown's avatar
unknown committed
837 838 839
  }

  if (!(select_options & SELECT_BIG_RESULT) &&
840
      ((group_list && const_tables != tables &&
841
	(!simple_group ||
842
	 !test_if_skip_sort_order(&join_tab[const_tables], group_list,
unknown's avatar
unknown committed
843 844
				  unit->select_limit_cnt, 0))) ||
       select_distinct) &&
845
      tmp_table_param.quick_group && !procedure)
unknown's avatar
unknown committed
846 847 848
  {
    need_tmp=1; simple_order=simple_group=0;	// Force tmp table without sort
  }
849

unknown's avatar
unknown committed
850
  tmp_having= having;
851
  if (select_options & SELECT_DESCRIBE)
852 853
  {
    error= 0;
854
    DBUG_RETURN(0);
855
  }
856 857 858 859 860 861 862 863 864
  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();
unknown's avatar
unknown committed
865

866 867 868 869 870 871 872 873 874 875 876
    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 :
877 878
			   HA_POS_ERROR,
			   (char *) "")))
879
      DBUG_RETURN(1);
880 881 882 883 884 885 886 887 888 889 890

    /*
      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
891
    if (tmp_having && 
892 893 894 895 896 897 898 899
	(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";
900
      if (create_sort_index(thd, this, group_list,
901
			    HA_POS_ERROR, HA_POS_ERROR) ||
902 903
	  alloc_group_fields(this, group_list) ||
	  make_sum_func_list(all_fields, fields_list, 1))
904 905 906 907 908
	DBUG_RETURN(1);
      group_list=0;
    }
    else
    {
909
      if (make_sum_func_list(all_fields, fields_list, 0))
910 911 912 913 914
	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";
915
	if (create_sort_index(thd, this, order,
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
                              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;
931
      JOIN_TAB *last_join_tab= join_tab+tables-1;
932 933
      do
      {
934
	if (used_tables & last_join_tab->table->map)
935
	  break;
936 937
	last_join_tab->not_used_in_distinct=1;
      } while (last_join_tab-- != join_tab);
938 939 940 941
      /* Optimize "select distinct b from t1 order by key_part_1 limit #" */
      if (order && skip_sort_order)
      {
 	/* Should always succeed */
942
	if (test_if_skip_sort_order(&join_tab[const_tables],
943 944 945 946 947
				    order, unit->select_limit_cnt, 0))
	  order=0;
      }
    }
    
948
    if (thd->lex->subqueries)
949 950 951
    {
      if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
	DBUG_RETURN(-1);
952
      error= 0;				// Ensure that tmp_join.error= 0
953 954 955 956
      restore_tmp();
    }
  }

957
  error= 0;
958 959 960
  DBUG_RETURN(0);
}

961

962
/*
963
  Restore values in temporary join
964
*/
965
void JOIN::restore_tmp()
966
{
967
  memcpy(tmp_join, this, (size_t) sizeof(JOIN));
968 969
}

970

971 972 973 974
int
JOIN::reinit()
{
  DBUG_ENTER("JOIN::reinit");
975
  /* TODO move to unit reinit */
976 977 978 979 980 981
  unit->offset_limit_cnt =select_lex->offset_limit;
  unit->select_limit_cnt =select_lex->select_limit+select_lex->offset_limit;
  if (unit->select_limit_cnt < select_lex->select_limit)
    unit->select_limit_cnt= HA_POS_ERROR;		// no limit
  if (unit->select_limit_cnt == HA_POS_ERROR)
    select_lex->options&= ~OPTION_FOUND_ROWS;
unknown's avatar
unknown committed
982
  
983
  if (setup_tables(tables_list))
984
    DBUG_RETURN(1);
unknown's avatar
unknown committed
985
  
986
  /* Reset of sum functions */
unknown's avatar
unknown committed
987
  first_record= 0;
unknown's avatar
unknown committed
988

989 990 991 992 993
  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
994
    filesort_free_buffers(exec_tmp_table1);
995 996 997 998 999 1000
  }
  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
1001
    filesort_free_buffers(exec_tmp_table2);
1002 1003
  }
  if (items0)
1004
    set_items_ref_array(items0);
1005

1006 1007 1008
  if (join_tab_save)
    memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * tables);

1009 1010 1011
  if (tmp_join)
    restore_tmp();

1012 1013 1014 1015 1016 1017 1018
  if (sum_funcs)
  {
    Item_sum *func, **func_ptr= sum_funcs;
    while ((func= *(func_ptr++)))
      func->clear();
  }

1019 1020 1021
  DBUG_RETURN(0);
}

1022 1023 1024 1025

bool
JOIN::save_join_tab()
{
unknown's avatar
unknown committed
1026
  if (!join_tab_save && select_lex->master_unit()->uncacheable)
1027
  {
unknown's avatar
unknown committed
1028 1029
    if (!(join_tab_save= (JOIN_TAB*)thd->memdup((gptr) join_tab,
						sizeof(JOIN_TAB) * tables)))
1030 1031 1032 1033 1034 1035
      return 1;
  }
  return 0;
}


1036
/*
1037
  Exec select
1038 1039 1040 1041 1042 1043
*/
void
JOIN::exec()
{
  int      tmp_error;
  DBUG_ENTER("JOIN::exec");
unknown's avatar
unknown committed
1044
  
1045
  error= 0;
unknown's avatar
unknown committed
1046 1047 1048 1049
  if (procedure)
  {
    if (procedure->change_columns(fields_list) ||
	result->prepare(fields_list, unit))
1050 1051
    {
      thd->limit_found_rows= thd->examined_row_count= 0;
unknown's avatar
unknown committed
1052
      DBUG_VOID_RETURN;
1053
    }
unknown's avatar
unknown committed
1054
  }
1055 1056 1057 1058 1059 1060 1061
  else if (test(select_options & OPTION_BUFFER_RESULT) &&
           result && result->prepare(fields_list, unit))
  {
    error= 1;
    thd->limit_found_rows= thd->examined_row_count= 0;
    DBUG_VOID_RETURN;
  }
1062

unknown's avatar
unknown committed
1063
  if (!tables_list)
1064 1065
  {                                           // Only test of functions
    if (select_options & SELECT_DESCRIBE)
unknown's avatar
unknown committed
1066
      select_describe(this, FALSE, FALSE, FALSE,
unknown's avatar
unknown committed
1067
		      (zero_result_cause?zero_result_cause:"No tables used"));
1068 1069 1070 1071 1072
    else
    {
      result->send_fields(fields_list,1);
      if (!having || having->val_int())
      {
1073 1074 1075
	if (do_send_rows && (procedure ? (procedure->send_row(fields_list) ||
                                          procedure->end_of_records())
                                       : result->send_data(fields_list)))
unknown's avatar
unknown committed
1076
	  error= 1;
1077
	else
1078
	{
unknown's avatar
unknown committed
1079
	  error= (int) result->send_eof();
1080 1081
	  send_records=1;
	}
1082 1083
      }
      else
1084
	error=(int) result->send_eof();
1085
    }
1086
    thd->limit_found_rows= thd->examined_row_count= 0;
1087 1088
    DBUG_VOID_RETURN;
  }
1089
  thd->limit_found_rows= thd->examined_row_count= 0;
1090 1091 1092

  if (zero_result_cause)
  {
unknown's avatar
unknown committed
1093
    (void) return_zero_rows(this, result, tables_list, fields_list,
1094
			    send_row_on_empty_set(),
unknown's avatar
unknown committed
1095 1096
			    select_options,
			    zero_result_cause,
1097
			    having, procedure,
unknown's avatar
unknown committed
1098
			    unit);
1099 1100 1101
    DBUG_VOID_RETURN;
  }

unknown's avatar
unknown committed
1102 1103
  if (select_options & SELECT_DESCRIBE)
  {
unknown's avatar
unknown committed
1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
    /*
      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
1119
    if (order &&
1120
	(const_tables == tables ||
unknown's avatar
unknown committed
1121
 	 ((simple_order || skip_sort_order) &&
1122
	  test_if_skip_sort_order(&join_tab[const_tables], order,
1123
				  select_limit, 0))))
unknown's avatar
unknown committed
1124
      order=0;
1125
    having= tmp_having;
1126
    select_describe(this, need_tmp,
1127
		    order != 0 && !skip_sort_order,
unknown's avatar
unknown committed
1128
		    select_distinct);
1129
    DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1130 1131
  }

1132 1133 1134 1135
  JOIN *curr_join= this;
  List<Item> *curr_all_fields= &all_fields;
  List<Item> *curr_fields_list= &fields_list;
  TABLE *curr_tmp_table= 0;
1136

unknown's avatar
unknown committed
1137 1138 1139
  /* Create a tmp table if distinct or if the sort is too complicated */
  if (need_tmp)
  {
1140 1141 1142
    if (tmp_join)
      curr_join= tmp_join;
    curr_tmp_table= exec_tmp_table1;
unknown's avatar
unknown committed
1143 1144

    /* Copy data to the temporary table */
1145
    thd->proc_info= "Copying to tmp table";
1146 1147
    
    if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
1148
    {
1149 1150
      error= tmp_error;
      DBUG_VOID_RETURN;
1151
    }
1152 1153 1154 1155 1156
    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
1157
    /* Change sum_fields reference to calculated fields in tmp_table */
1158 1159
    curr_join->all_fields= *curr_all_fields;
    if (!items1)
unknown's avatar
unknown committed
1160
    {
1161 1162 1163
      items1= items0 + all_fields.elements;
      if (sort_and_group || curr_tmp_table->group)
      {
1164
	if (change_to_use_tmp_fields(thd, items1,
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181
				     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;
1182
    set_items_ref_array(items1);
1183 1184 1185 1186 1187 1188 1189 1190
    
    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
1191 1192 1193
    }
    else
    {
1194 1195 1196
      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
1197
    }
1198 1199
    
    // procedure can't be used inside subselect => we do nothing special for it
unknown's avatar
unknown committed
1200 1201
    if (procedure)
      procedure->update_refs();
1202 1203
    
    if (curr_tmp_table->group)
unknown's avatar
unknown committed
1204
    {						// Already grouped
unknown's avatar
unknown committed
1205
      if (!curr_join->order && !curr_join->no_order && !skip_sort_order)
1206 1207
	curr_join->order= curr_join->group_list;  /* order by group */
      curr_join->group_list= 0;
unknown's avatar
unknown committed
1208
    }
1209
    
unknown's avatar
unknown committed
1210
    /*
1211 1212 1213 1214 1215
      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
1216 1217
    */

1218 1219 1220 1221 1222
    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
1223 1224
    {					/* Must copy to another table */
      DBUG_PRINT("info",("Creating group table"));
1225
      
unknown's avatar
unknown committed
1226
      /* Free first data from old join */
1227
      curr_join->join_free(0);
1228
      if (make_simple_join(curr_join, curr_tmp_table))
unknown's avatar
unknown committed
1229
	DBUG_VOID_RETURN;
1230
      calc_group_buffer(curr_join, group_list);
1231 1232
      count_field_types(&curr_join->tmp_table_param,
			curr_join->tmp_all_fields1,
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
			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,
1252 1253
						HA_POS_ERROR,
						(char *) "")))
1254 1255 1256
	  DBUG_VOID_RETURN;
	curr_join->exec_tmp_table2= exec_tmp_table2;
      }
1257
      if (curr_join->group_list)
unknown's avatar
unknown committed
1258
      {
1259
	thd->proc_info= "Creating sort index";
1260 1261 1262 1263
	if (curr_join->join_tab == join_tab && save_join_tab())
	{
	  DBUG_VOID_RETURN;
	}
1264
	if (create_sort_index(thd, curr_join, curr_join->group_list,
1265
			      HA_POS_ERROR, HA_POS_ERROR) ||
1266
	    make_group_fields(this, curr_join))
unknown's avatar
unknown committed
1267
	{
1268
	  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1269
	}
1270
	curr_join->group_list= 0;
unknown's avatar
unknown committed
1271
      }
1272
      
unknown's avatar
unknown committed
1273
      thd->proc_info="Copying to group table";
1274
      tmp_error= -1;
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288
      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;
	}
      }
1289 1290
      if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
					1) ||
1291 1292
	  (tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
				0)))
unknown's avatar
unknown committed
1293
      {
1294
	error= tmp_error;
1295
	DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1296
      }
1297 1298 1299 1300 1301 1302 1303 1304
      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;
1305
	if (change_to_use_tmp_fields(thd, items2,
1306 1307 1308 1309 1310 1311 1312 1313
				     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;
1314
      set_items_ref_array(items2);
1315 1316 1317 1318 1319 1320 1321
      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 */
    
1322
    curr_join->join_free(0);			/* Free quick selects */
1323
    if (curr_join->select_distinct && ! curr_join->group_list)
unknown's avatar
unknown committed
1324 1325
    {
      thd->proc_info="Removing duplicates";
1326 1327 1328 1329
      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))
1330
	DBUG_VOID_RETURN;
1331 1332
      curr_join->tmp_having=0;
      curr_join->select_distinct=0;
unknown's avatar
unknown committed
1333
    }
1334 1335
    curr_tmp_table->reginfo.lock_type= TL_UNLOCK;
    if (make_simple_join(curr_join, curr_tmp_table))
1336
      DBUG_VOID_RETURN;
1337 1338 1339
    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
1340 1341
  }
  if (procedure)
1342 1343 1344
    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
1345 1346
      (procedure && (procedure->flags & PROC_GROUP)))
  {
1347 1348 1349 1350
    if (make_group_fields(this, curr_join))
    {
      DBUG_VOID_RETURN;
    }
1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374
    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;
1375
    set_items_ref_array(items3);
1376

1377 1378
    if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
				      1) || thd->is_fatal_error)
1379
      DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1380
  }
1381
  if (curr_join->group_list || curr_join->order)
unknown's avatar
unknown committed
1382 1383 1384 1385
  {
    DBUG_PRINT("info",("Sorting for send_fields"));
    thd->proc_info="Sorting result";
    /* If we have already done the group, add HAVING to sorted table */
1386 1387
    if (curr_join->tmp_having && ! curr_join->group_list && 
	! curr_join->sort_and_group)
unknown's avatar
unknown committed
1388
    {
1389 1390
      // Some tables may have been const
      curr_join->tmp_having->update_used_tables();
1391 1392 1393
      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
1394

1395 1396
      Item* sort_table_cond= make_cond_for_table(curr_join->tmp_having,
						 used_tables,
1397
						 used_tables);
unknown's avatar
unknown committed
1398 1399
      if (sort_table_cond)
      {
1400 1401
	if (!curr_table->select)
	  if (!(curr_table->select= new SQL_SELECT))
1402
	    DBUG_VOID_RETURN;
1403 1404
	if (!curr_table->select->cond)
	  curr_table->select->cond= sort_table_cond;
unknown's avatar
unknown committed
1405
	else					// This should never happen
1406
	{
1407
	  if (!(curr_table->select->cond=
1408
		new Item_cond_and(curr_table->select->cond,
unknown's avatar
unknown committed
1409
				  sort_table_cond)))
1410
	    DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1411 1412 1413 1414 1415
	  /*
	    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();
1416
	}
1417
	curr_table->select_cond= curr_table->select->cond;
1418 1419
	curr_table->select_cond->top_level_item();
	DBUG_EXECUTE("where",print_where(curr_table->select->cond,
unknown's avatar
unknown committed
1420
					 "select and having"););
1421 1422 1423
	curr_join->tmp_having= make_cond_for_table(curr_join->tmp_having,
						   ~ (table_map) 0,
						   ~used_tables);
unknown's avatar
unknown committed
1424 1425 1426
	DBUG_EXECUTE("where",print_where(conds,"having after sort"););
      }
    }
unknown's avatar
unknown committed
1427
    {
unknown's avatar
unknown committed
1428
      if (group)
1429
	curr_join->select_limit= HA_POS_ERROR;
unknown's avatar
unknown committed
1430
      else
unknown's avatar
unknown committed
1431
      {
unknown's avatar
unknown committed
1432 1433 1434 1435
	/*
	  We can abort sorting after thd->select_limit rows if we there is no
	  WHERE clause for any tables after the sorted one.
	*/
1436
	JOIN_TAB *curr_table= &curr_join->join_tab[curr_join->const_tables+1];
1437
	JOIN_TAB *end_table= &curr_join->join_tab[curr_join->tables];
1438
	for (; curr_table < end_table ; curr_table++)
unknown's avatar
unknown committed
1439
	{
unknown's avatar
unknown committed
1440 1441 1442 1443 1444 1445
	  /*
	    table->keyuse is set in the case there was an original WHERE clause
	    on the table that was optimized away.
	    table->on_expr tells us that it was a LEFT JOIN and there will be
	    at least one row generated from the table.
	  */
1446 1447
	  if (curr_table->select_cond ||
	      (curr_table->keyuse && !curr_table->on_expr))
unknown's avatar
unknown committed
1448 1449
	  {
	    /* We have to sort all rows */
1450
	    curr_join->select_limit= HA_POS_ERROR;
unknown's avatar
unknown committed
1451 1452
	    break;
	  }
unknown's avatar
unknown committed
1453 1454
	}
      }
1455 1456 1457 1458
      if (curr_join->join_tab == join_tab && save_join_tab())
      {
	DBUG_VOID_RETURN;
      }
unknown's avatar
unknown committed
1459 1460 1461 1462 1463 1464 1465 1466 1467
      /*
	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.
      */
1468
      if (create_sort_index(thd, curr_join,
1469 1470
			    curr_join->group_list ? 
			    curr_join->group_list : curr_join->order,
unknown's avatar
unknown committed
1471 1472 1473
			    curr_join->select_limit,
			    (select_options & OPTION_FOUND_ROWS ?
			     HA_POS_ERROR : unit->select_limit_cnt)))
1474
	DBUG_VOID_RETURN;
unknown's avatar
unknown committed
1475
    }
unknown's avatar
unknown committed
1476
  }
1477
  curr_join->having= curr_join->tmp_having;
unknown's avatar
unknown committed
1478
  thd->proc_info="Sending data";
1479
  error= thd->net.report_error ? -1 :
1480
    do_select(curr_join, curr_fields_list, NULL, procedure);
unknown's avatar
unknown committed
1481 1482
  thd->limit_found_rows= curr_join->send_records;
  thd->examined_row_count= curr_join->examined_rows;
1483 1484
  DBUG_VOID_RETURN;
}
unknown's avatar
unknown committed
1485

1486

1487 1488 1489 1490 1491
/*
  Clean up join. Return error that hold JOIN.
*/

int
1492
JOIN::cleanup()
1493
{
1494
  DBUG_ENTER("JOIN::cleanup");
1495 1496 1497
  select_lex->join= 0;

  if (tmp_join)
unknown's avatar
unknown committed
1498 1499 1500 1501 1502 1503
  {
    if (join_tab != tmp_join->join_tab)
    {
      JOIN_TAB *tab, *end;
      for (tab= join_tab, end= tab+tables ; tab != end ; tab++)
      {
1504
	tab->cleanup();
unknown's avatar
unknown committed
1505 1506 1507
      }
    }
    tmp_join->tmp_join= 0;
unknown's avatar
unknown committed
1508
    tmp_table_param.copy_field=0;
1509
    DBUG_RETURN(tmp_join->cleanup());
unknown's avatar
unknown committed
1510
  }
1511

1512
  lock=0;                                     // It's faster to unlock later
1513
  join_free(1);
unknown's avatar
unknown committed
1514 1515 1516 1517
  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
1518 1519 1520
  delete select;
  delete_dynamic(&keyuse);
  delete procedure;
1521 1522 1523
  for (SELECT_LEX_UNIT *lex_unit= select_lex->first_inner_unit();
       lex_unit != 0;
       lex_unit= lex_unit->next_unit())
1524
  {
1525
    error|= lex_unit->cleanup();
1526 1527
  }
  DBUG_RETURN(error);
1528 1529
}

1530

1531
int
1532
mysql_select(THD *thd, Item ***rref_pointer_array,
unknown's avatar
unknown committed
1533
	     TABLE_LIST *tables, uint wild_num, List<Item> &fields,
1534 1535 1536
	     COND *conds, uint og_num,  ORDER *order, ORDER *group,
	     Item *having, ORDER *proc_param, ulong select_options,
	     select_result *result, SELECT_LEX_UNIT *unit,
1537
	     SELECT_LEX *select_lex)
1538
{
unknown's avatar
unknown committed
1539 1540
  int err;
  bool free_join= 1;
1541 1542
  DBUG_ENTER("mysql_select");

unknown's avatar
unknown committed
1543
  JOIN *join;
1544
  if (select_lex->join != 0)
1545
  {
unknown's avatar
unknown committed
1546
    join= select_lex->join;
1547 1548 1549
    // is it single SELECT in derived table, called in derived table creation
    if (select_lex->linkage != DERIVED_TABLE_TYPE ||
	(select_options & SELECT_DESCRIBE))
unknown's avatar
unknown committed
1550
    {
1551
      if (select_lex->linkage != GLOBAL_OPTIONS_TYPE)
1552
      {
1553
	//here is EXPLAIN of subselect or derived table
1554
	if (join->change_result(result))
1555 1556 1557
	{
	  DBUG_RETURN(-1);
	}
1558
      }
1559
      else
1560
      {
1561 1562 1563 1564 1565 1566
	if (join->prepare(rref_pointer_array, tables, wild_num,
			  conds, og_num, order, group, having, proc_param,
			  select_lex, unit))
	{
	  goto err;
	}
1567
      }
unknown's avatar
unknown committed
1568
    }
1569
    free_join= 0;
unknown's avatar
unknown committed
1570
    join->select_options= select_options;
1571
  }
unknown's avatar
unknown committed
1572 1573
  else
  {
1574 1575
    if (!(join= new JOIN(thd, fields, select_options, result)))
	DBUG_RETURN(-1);
unknown's avatar
unknown committed
1576 1577
    thd->proc_info="init";
    thd->used_tables=0;                         // Updated by setup_fields
1578 1579
    if (join->prepare(rref_pointer_array, tables, wild_num,
		      conds, og_num, order, group, having, proc_param,
1580
		      select_lex, unit))
unknown's avatar
unknown committed
1581
    {
1582
      goto err;
unknown's avatar
unknown committed
1583 1584 1585
    }
  }

unknown's avatar
unknown committed
1586
  if ((err= join->optimize()))
unknown's avatar
unknown committed
1587
  {
unknown's avatar
unknown committed
1588 1589
    goto err;					// 1
  }
1590

1591
  if (thd->lex->describe & DESCRIBE_EXTENDED)
unknown's avatar
unknown committed
1592 1593 1594 1595 1596
  {
    join->conds_history= join->conds;
    join->having_history= (join->having?join->having:join->tmp_having);
  }

1597
  if (thd->net.report_error)
1598 1599 1600 1601
    goto err;

  join->exec();

1602
  if (thd->lex->describe & DESCRIBE_EXTENDED)
unknown's avatar
unknown committed
1603 1604 1605 1606 1607
  {
    select_lex->where= join->conds_history;
    select_lex->having= join->having_history;
  }

1608
err:
unknown's avatar
unknown committed
1609 1610 1611
  if (free_join)
  {
    thd->proc_info="end";
1612
    err= join->cleanup();
unknown's avatar
unknown committed
1613 1614
    if (thd->net.report_error)
      err= -1;
unknown's avatar
unknown committed
1615
    delete join;
unknown's avatar
unknown committed
1616
    DBUG_RETURN(err);
unknown's avatar
unknown committed
1617
  }
unknown's avatar
unknown committed
1618
  DBUG_RETURN(join->error);
unknown's avatar
unknown committed
1619 1620 1621
}

/*****************************************************************************
1622 1623
  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
1624 1625
*****************************************************************************/

1626 1627
static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
				      TABLE *table,
unknown's avatar
unknown committed
1628
				      const key_map *keys,ha_rows limit)
unknown's avatar
unknown committed
1629 1630 1631 1632 1633 1634 1635
{
  int error;
  DBUG_ENTER("get_quick_record_count");
  if (select)
  {
    select->head=table;
    table->reginfo.impossible_range=0;
1636 1637
    if ((error=select->test_quick_select(thd, *(key_map *)keys,(table_map) 0,
					 limit)) == 1)
unknown's avatar
unknown committed
1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649
      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 */
}


1650 1651 1652 1653 1654 1655 1656
/*
  Calculate the best possible join and initialize the join structure

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

unknown's avatar
unknown committed
1658 1659
static bool
make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
1660
		     DYNAMIC_ARRAY *keyuse_array)
unknown's avatar
unknown committed
1661 1662
{
  int error;
1663 1664 1665
  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
1666 1667 1668 1669 1670 1671 1672 1673
  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;
1674 1675
  stat=(JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB)*table_count);
  stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)*MAX_TABLES);
1676
  table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*(table_count*2));
unknown's avatar
unknown committed
1677 1678 1679 1680 1681 1682
  if (!stat || !stat_ref || !table_vector)
    DBUG_RETURN(1);				// Eom /* purecov: inspected */

  join->best_ref=stat_vector;

  stat_end=stat+table_count;
1683
  found_const_table_map= all_table_map=0;
unknown's avatar
unknown committed
1684 1685 1686 1687 1688 1689
  const_count=0;

  for (s=stat,i=0 ; tables ; s++,tables=tables->next,i++)
  {
    TABLE *table;
    stat_vector[i]=s;
1690 1691 1692 1693
    s->keys.init();
    s->const_keys.init();
    s->checked_keys.init();
    s->needed_reg.init();
unknown's avatar
unknown committed
1694 1695
    table_vector[i]=s->table=table=tables->table;
    table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);// record count
1696
    table->quick_keys.clear_all();
unknown's avatar
unknown committed
1697 1698 1699 1700
    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;
1701
    s->join=join;
1702
    s->info=0;					// For describe
unknown's avatar
unknown committed
1703 1704
    if ((s->on_expr=tables->on_expr))
    {
1705
      /* Left join */
unknown's avatar
unknown committed
1706 1707
      if (!table->file->records)
      {						// Empty table
1708
	s->key_dependent=s->dependent=0;	// Ignore LEFT JOIN depend.
unknown's avatar
unknown committed
1709 1710 1711
	set_position(join,const_count++,s,(KEYUSE*) 0);
	continue;
      }
unknown's avatar
unknown committed
1712 1713
      s->key_dependent=s->dependent=
	s->on_expr->used_tables() & ~(table->map);
1714 1715 1716 1717
      if (table->outer_join & JOIN_TYPE_LEFT)
	s->dependent|=stat_vector[i-1]->dependent | table_vector[i-1]->map;
      if (tables->outer_join & JOIN_TYPE_RIGHT)
	s->dependent|=tables->next->table->map;
unknown's avatar
unknown committed
1718 1719 1720 1721 1722 1723 1724 1725
      outer_join|=table->map;
      continue;
    }
    if (tables->straight)			// We don't have to move this
      s->dependent= table_vector[i-1]->map | stat_vector[i-1]->dependent;
    else
      s->dependent=(table_map) 0;
    s->key_dependent=(table_map) 0;
unknown's avatar
unknown committed
1726
    if ((table->system || table->file->records <= 1) && ! s->dependent &&
1727
	!(table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
unknown's avatar
unknown committed
1728
        !table->fulltext_searched)
unknown's avatar
unknown committed
1729 1730 1731 1732 1733
    {
      set_position(join,const_count++,s,(KEYUSE*) 0);
    }
  }
  stat_vector[i]=0;
1734
  join->outer_join=outer_join;
unknown's avatar
unknown committed
1735 1736

  /*
1737 1738 1739 1740
    If outer join: Re-arrange tables in stat_vector so that outer join
    tables are after all tables it is dependent of.
    For example: SELECT * from A LEFT JOIN B ON B.c=C.c, C WHERE A.C=C.C
    Will shift table B after table C.
unknown's avatar
unknown committed
1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772
  */
  if (outer_join)
  {
    table_map used_tables=0L;
    for (i=0 ; i < join->tables-1 ; i++)
    {
      if (stat_vector[i]->dependent & ~used_tables)
      {
	JOIN_TAB *save= stat_vector[i];
	uint j;
	for (j=i+1;
	     j < join->tables && stat_vector[j]->dependent & ~used_tables;
	     j++)
	{
	  JOIN_TAB *tmp=stat_vector[j];		// Move element up
	  stat_vector[j]=save;
	  save=tmp;
	}
	if (j == join->tables)
	{
	  join->tables=0;			// Don't use join->table
	  my_error(ER_WRONG_OUTER_JOIN,MYF(0));
	  DBUG_RETURN(1);
	}
	stat_vector[i]=stat_vector[j];
	stat_vector[j]=save;
      }
      used_tables|= stat_vector[i]->table->map;
    }
  }

  if (conds || outer_join)
1773 1774
    if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables,
                            conds, ~outer_join, join->select_lex))
unknown's avatar
unknown committed
1775 1776
      DBUG_RETURN(1);

1777
  /* Read tables with 0 or 1 rows (system tables) */
1778
  join->const_table_map= 0;
1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796

  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
1797
  /* loop until no more const tables are found */
1798
  int ref_changed;
unknown's avatar
unknown committed
1799 1800
  do
  {
1801
    ref_changed = 0;
unknown's avatar
unknown committed
1802
    found_ref=0;
1803 1804 1805 1806 1807 1808 1809

    /*
      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
1810
    {
1811
      TABLE *table=s->table;
unknown's avatar
unknown committed
1812 1813
      if (s->dependent)				// If dependent on some table
      {
1814
	// All dep. must be constants
1815
	if (s->dependent & ~(found_const_table_map))
unknown's avatar
unknown committed
1816
	  continue;
1817
	if (table->file->records <= 1L &&
1818
	    !(table->file->table_flags() & HA_NOT_EXACT_COUNT))
unknown's avatar
unknown committed
1819
	{					// system table
1820
	  int tmp= 0;
unknown's avatar
unknown committed
1821
	  s->type=JT_SYSTEM;
1822
	  join->const_table_map|=table->map;
unknown's avatar
unknown committed
1823
	  set_position(join,const_count++,s,(KEYUSE*) 0);
1824
	  if ((tmp= join_read_const_table(s,join->positions+const_count-1)))
1825 1826 1827 1828 1829 1830
	  {
	    if (tmp > 0)
	      DBUG_RETURN(1);			// Fatal error
	  }
	  else
	    found_const_table_map|= table->map;
unknown's avatar
unknown committed
1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841
	  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;
1842
	  s->keys.set_bit(key);               // QQ: remove this ?
unknown's avatar
unknown committed
1843

1844 1845 1846
	  refs=0;
          const_ref.clear_all();
	  eq_part.clear_all();
unknown's avatar
unknown committed
1847 1848
	  do
	  {
1849
	    if (keyuse->val->type() != Item::NULL_ITEM && !keyuse->optimize)
unknown's avatar
unknown committed
1850
	    {
1851
	      if (!((~found_const_table_map) & keyuse->used_tables))
1852
		const_ref.set_bit(keyuse->keypart);
unknown's avatar
unknown committed
1853 1854
	      else
		refs|=keyuse->used_tables;
1855
	      eq_part.set_bit(keyuse->keypart);
unknown's avatar
unknown committed
1856 1857 1858 1859
	    }
	    keyuse++;
	  } while (keyuse->table == table && keyuse->key == key);

1860
	  if (eq_part.is_prefix(table->key_info[key].key_parts) &&
1861 1862
	      ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY)) ==
	       HA_NOSAME) &&
unknown's avatar
unknown committed
1863
              !table->fulltext_searched)
unknown's avatar
unknown committed
1864 1865 1866
	  {
	    if (const_ref == eq_part)
	    {					// Found everything for ref.
1867 1868
	      int tmp;
	      ref_changed = 1;
1869
	      s->type= JT_CONST;
1870
	      join->const_table_map|=table->map;
unknown's avatar
unknown committed
1871
	      set_position(join,const_count++,s,start_keyuse);
1872
	      if (create_ref_for_key(join, s, start_keyuse,
1873
				     found_const_table_map))
1874 1875 1876 1877 1878 1879 1880 1881 1882
		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
1883 1884 1885 1886 1887 1888 1889 1890
	      break;
	    }
	    else
	      found_ref|= refs;		// Table is const if all refs are const
	  }
	}
      }
    }
1891
  } while (join->const_table_map & found_ref && ref_changed);
unknown's avatar
unknown committed
1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904

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

1907 1908
    /*
      Set a max range of how many seeks we can expect when using keys
1909 1910
      This is can't be to high as otherwise we are likely to use
      table scan.
1911
    */
1912 1913
    s->worst_seeks= min((double) s->found_records / 10,
			(double) s->read_time*3);
unknown's avatar
unknown committed
1914 1915 1916
    if (s->worst_seeks < 2.0)			// Fix for small tables
      s->worst_seeks=2.0;

1917
    if (! s->const_keys.is_clear_all())
unknown's avatar
unknown committed
1918 1919
    {
      ha_rows records;
1920 1921 1922 1923 1924
      SQL_SELECT *select;
      select= make_select(s->table, found_const_table_map,
			  found_const_table_map,
			  s->on_expr ? s->on_expr : conds,
			  &error);
1925
      records= get_quick_record_count(join->thd, select, s->table,
unknown's avatar
unknown committed
1926
				      &s->const_keys, join->row_limit);
unknown's avatar
unknown committed
1927 1928 1929
      s->quick=select->quick;
      s->needed_reg=select->needed_reg;
      select->quick=0;
1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949
      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;
	if (s->on_expr)
	{
	  /* 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
1950 1951
      if (records != HA_POS_ERROR)
      {
1952
	s->found_records=records;
unknown's avatar
unknown committed
1953 1954
	s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
      }
1955
      delete select;
unknown's avatar
unknown committed
1956 1957 1958 1959 1960 1961 1962 1963
    }
  }

  /* Find best combination and return it */
  join->join_tab=stat;
  join->map2table=stat_ref;
  join->table= join->all_tables=table_vector;
  join->const_tables=const_count;
1964
  join->found_const_table_map=found_const_table_map;
unknown's avatar
unknown committed
1965 1966

  if (join->const_tables != join->tables)
1967 1968
  {
    optimize_keyuse(join, keyuse_array);
1969
    find_best_combination(join,all_table_map & ~join->const_table_map);
1970
  }
unknown's avatar
unknown committed
1971 1972 1973 1974 1975 1976
  else
  {
    memcpy((gptr) join->best_positions,(gptr) join->positions,
	   sizeof(POSITION)*join->const_tables);
    join->best_read=1.0;
  }
unknown's avatar
unknown committed
1977
  DBUG_RETURN(join->thd->killed || get_best_combination(join));
unknown's avatar
unknown committed
1978 1979 1980 1981
}


/*****************************************************************************
1982 1983 1984 1985 1986
  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
1987 1988 1989 1990 1991
*****************************************************************************/

typedef struct key_field_t {		// Used when finding key fields
  Field		*field;
  Item		*val;			// May be empty if diff constant
1992 1993
  uint		level;
  uint		optimize;
unknown's avatar
unknown committed
1994 1995 1996
  bool		eq_func;
} KEY_FIELD;

1997 1998 1999 2000 2001 2002 2003 2004
/* 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
2005

2006 2007 2008 2009 2010 2011
  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
2012 2013 2014 2015 2016 2017 2018 2019

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
2020
    return start;				// No new fields, skip all
unknown's avatar
unknown committed
2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032

  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())
	{
2033 2034 2035 2036
	  /*
	    If the value matches, we can use the key reference.
	    If not, we keep it until we have examined all new values
	  */
2037
	  if (old->val->eq(new_fields->val, old->field->binary()))
unknown's avatar
unknown committed
2038
	  {
2039 2040 2041 2042 2043
	    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
2044 2045
	  }
	}
2046 2047
	else if (old->eq_func && new_fields->eq_func &&
		 old->val->eq(new_fields->val, old->field->binary()))
2048

2049 2050 2051 2052 2053 2054 2055 2056 2057
	{
	  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
2058
	{
2059 2060 2061 2062 2063 2064
	  /* 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
2065
	}
2066
	else
unknown's avatar
unknown committed
2067
	{
2068 2069 2070 2071 2072
	  /*
	    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
2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083
	  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 ;)
  {
2084
    if (old->level != and_level)
unknown's avatar
unknown committed
2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096
    {						// Not used in all levels
      if (old == --first_free)
	break;
      *old= *first_free;			// Remove old value
      continue;
    }
    old++;
  }
  return first_free;
}


2097 2098 2099 2100 2101 2102 2103 2104 2105 2106
/*
  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
    field			Field used in comparision
    eq_func			True if we used =, <=> or IS NULL
    value			Value used for comparison with field
2107
                                Is NULL for BETWEEN and IN
2108 2109 2110 2111 2112 2113 2114 2115 2116 2117
    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
2118
static void
2119
add_key_field(KEY_FIELD **key_fields,uint and_level, COND *cond,
2120
	      Field *field,bool eq_func,Item **value, uint num_values,
unknown's avatar
unknown committed
2121 2122
	      table_map usable_tables)
{
2123
  uint exists_optimize= 0;
unknown's avatar
unknown committed
2124 2125 2126
  if (!(field->flags & PART_KEY_FLAG))
  {
    // Don't remove column IS NULL on a LEFT JOIN table
2127 2128
    if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
        !field->table->maybe_null || field->null_ptr)
unknown's avatar
unknown committed
2129
      return;					// Not a key. Skip it
2130
    exists_optimize= KEY_OPTIMIZE_EXISTS;
unknown's avatar
unknown committed
2131 2132 2133 2134
  }
  else
  {
    table_map used_tables=0;
2135 2136 2137
    bool optimizable=0;
    for (uint i=0; i<num_values; i++)
    {
unknown's avatar
unknown committed
2138 2139
      used_tables|=(value[i])->used_tables();
      if (!((value[i])->used_tables() & (field->table->map | RAND_TABLE_BIT)))
2140 2141 2142
        optimizable=1;
    }
    if (!optimizable)
unknown's avatar
unknown committed
2143 2144 2145
      return;
    if (!(usable_tables & field->table->map))
    {
2146 2147
      if (!eq_func || (*value)->type() != Item::NULL_ITEM ||
          !field->table->maybe_null || field->null_ptr)
unknown's avatar
unknown committed
2148
	return;					// Can't use left join optimize
2149
      exists_optimize= KEY_OPTIMIZE_EXISTS;
unknown's avatar
unknown committed
2150 2151 2152 2153
    }
    else
    {
      JOIN_TAB *stat=field->table->reginfo.join_tab;
unknown's avatar
unknown committed
2154
      key_map possible_keys=field->key_start;
2155 2156
      possible_keys.intersect(field->table->keys_in_use_for_query);
      stat[0].keys.merge(possible_keys);             // Add possible keys
unknown's avatar
unknown committed
2157

2158 2159 2160 2161 2162 2163 2164 2165
      /*
	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
2166 2167
         Field BETWEEN ...
         Field IN ...
unknown's avatar
unknown committed
2168 2169 2170
      */
      stat[0].key_dependent|=used_tables;

2171 2172
      bool is_const=1;
      for (uint i=0; i<num_values; i++)
2173
        is_const&= value[i]->const_item();
2174
      if (is_const)
2175
        stat[0].const_keys.merge(possible_keys);
2176 2177
      /*
	We can't always use indexes when comparing a string index to a
unknown's avatar
unknown committed
2178 2179
	number. cmp_type() is checked to allow compare of dates to numbers.
        eq_func is NEVER true when num_values > 1
2180
       */
unknown's avatar
unknown committed
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194
      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.
2195

unknown's avatar
unknown committed
2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206
            We can also not used 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
2207 2208
    }
  }
2209
  DBUG_ASSERT(num_values == 1);
unknown's avatar
unknown committed
2210 2211 2212 2213 2214
  /*
    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
2215
  /* Store possible eq field */
2216 2217
  (*key_fields)->field=		field;
  (*key_fields)->eq_func=	eq_func;
unknown's avatar
unknown committed
2218
  (*key_fields)->val=		*value;
2219 2220
  (*key_fields)->level=		and_level;
  (*key_fields)->optimize=	exists_optimize;
unknown's avatar
unknown committed
2221 2222 2223 2224 2225 2226 2227 2228 2229 2230
  (*key_fields)++;
}


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
2231
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
2232 2233 2234 2235 2236 2237 2238 2239
    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++)
2240
	org_key_fields->level= *and_level;
unknown's avatar
unknown committed
2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266
    }
    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
2267
    // BETWEEN, IN, NOT
2268
    if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM &&
unknown's avatar
unknown committed
2269
	!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
2270
      add_key_field(key_fields,*and_level,cond_func,
unknown's avatar
unknown committed
2271 2272 2273
		    ((Item_field*)(cond_func->key_item()->real_item()))->field,
                    cond_func->argument_count() == 2 &&
                    cond_func->functype() == Item_func::IN_FUNC,
2274 2275
                    cond_func->arguments()+1, cond_func->argument_count()-1,
                    usable_tables);
unknown's avatar
unknown committed
2276 2277 2278 2279 2280 2281
    break;
  case Item_func::OPTIMIZE_OP:
  {
    bool equal_func=(cond_func->functype() == Item_func::EQ_FUNC ||
		     cond_func->functype() == Item_func::EQUAL_FUNC);

2282
    if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
unknown's avatar
unknown committed
2283
	!(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
2284
    {
2285
      add_key_field(key_fields,*and_level,cond_func,
unknown's avatar
unknown committed
2286 2287
		    ((Item_field*) (cond_func->arguments()[0])->real_item())
		    ->field,
unknown's avatar
unknown committed
2288
		    equal_func,
2289
                    cond_func->arguments()+1, 1, usable_tables);
unknown's avatar
unknown committed
2290
    }
unknown's avatar
unknown committed
2291
    if (cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
2292
	cond_func->functype() != Item_func::LIKE_FUNC &&
unknown's avatar
unknown committed
2293
	!(cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
2294
    {
2295
      add_key_field(key_fields,*and_level,cond_func,
unknown's avatar
unknown committed
2296 2297
		    ((Item_field*) (cond_func->arguments()[1])->real_item())
		    ->field,
unknown's avatar
unknown committed
2298
		    equal_func,
2299
		    cond_func->arguments(),1,usable_tables);
unknown's avatar
unknown committed
2300 2301 2302 2303 2304
    }
    break;
  }
  case Item_func::OPTIMIZE_NULL:
    /* column_name IS [NOT] NULL */
2305
    if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
unknown's avatar
unknown committed
2306
	!(cond_func->used_tables() & OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
2307
    {
2308
      Item *tmp=new Item_null;
2309
      if (unlikely(!tmp))                       // Should never be true
unknown's avatar
unknown committed
2310
	return;
2311
      add_key_field(key_fields,*and_level,cond_func,
unknown's avatar
unknown committed
2312 2313
		    ((Item_field*) (cond_func->arguments()[0])->real_item())
		    ->field,
unknown's avatar
unknown committed
2314
		    cond_func->functype() == Item_func::ISNULL_FUNC,
2315
		    &tmp, 1, usable_tables);
unknown's avatar
unknown committed
2316 2317 2318 2319 2320 2321 2322
    }
    break;
  }
  return;
}

/*
2323 2324
  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
2325 2326 2327
*/

static uint
2328
max_part_bit(key_part_map bits)
unknown's avatar
unknown committed
2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341
{
  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;

2342
  if (key_field->eq_func && !(key_field->optimize & KEY_OPTIMIZE_EXISTS))
unknown's avatar
unknown committed
2343 2344 2345
  {
    for (uint key=0 ; key < form->keys ; key++)
    {
2346
      if (!(form->keys_in_use_for_query.is_set(key)))
unknown's avatar
unknown committed
2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359
	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;
2360
	  keyuse.keypart_map= (key_part_map) 1 << part;
unknown's avatar
unknown committed
2361
	  keyuse.used_tables=key_field->val->used_tables();
2362
	  keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL;
unknown's avatar
unknown committed
2363 2364 2365 2366 2367 2368 2369
	  VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
	}
      }
    }
  }
}

unknown's avatar
unknown committed
2370 2371 2372

#define FT_KEYPART   (MAX_REF_PARTS+10)

unknown's avatar
unknown committed
2373 2374 2375 2376
static void
add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
            JOIN_TAB *stat,COND *cond,table_map usable_tables)
{
2377
  Item_func_match *cond_func=NULL;
unknown's avatar
unknown committed
2378

2379 2380 2381
  if (!cond)
    return;

2382 2383
  if (cond->type() == Item::FUNC_ITEM)
  {
2384 2385 2386
    Item_func *func=(Item_func *)cond;
    Item_func::Functype functype=  func->functype();
    if (functype == Item_func::FT_FUNC)
2387
      cond_func=(Item_func_match *)cond;
2388 2389 2390 2391
    else if (func->arg_count == 2)
    {
      Item_func *arg0=(Item_func *)(func->arguments()[0]),
                *arg1=(Item_func *)(func->arguments()[1]);
2392 2393 2394 2395 2396
      if (arg1->const_item()  &&
          ((functype == Item_func::GE_FUNC && arg1->val()> 0) ||
           (functype == Item_func::GT_FUNC && arg1->val()>=0))  &&
           arg0->type() == Item::FUNC_ITEM            &&
           arg0->functype() == Item_func::FT_FUNC)
2397
        cond_func=(Item_func_match *) arg0;
2398 2399 2400
      else if (arg0->const_item() &&
               ((functype == Item_func::LE_FUNC && arg0->val()> 0) ||
                (functype == Item_func::LT_FUNC && arg0->val()>=0)) &&
2401
                arg1->type() == Item::FUNC_ITEM          &&
2402
                arg1->functype() == Item_func::FT_FUNC)
2403 2404
        cond_func=(Item_func_match *) arg1;
    }
2405 2406 2407
  }
  else if (cond->type() == Item::COND_ITEM)
  {
unknown's avatar
unknown committed
2408
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
2409 2410 2411 2412 2413

    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
    {
      Item *item;
      while ((item=li++))
2414
        add_ft_keys(keyuse_array,stat,item,usable_tables);
2415 2416 2417
    }
  }

2418 2419
  if (!cond_func || cond_func->key == NO_SUCH_KEY ||
      !(usable_tables & cond_func->table->map))
2420
    return;
unknown's avatar
unknown committed
2421 2422 2423

  KEYUSE keyuse;
  keyuse.table= cond_func->table;
2424
  keyuse.val =  cond_func;
unknown's avatar
unknown committed
2425
  keyuse.key =  cond_func->key;
unknown's avatar
unknown committed
2426
  keyuse.keypart= FT_KEYPART;
2427
  keyuse.used_tables=cond_func->key_item()->used_tables();
unknown's avatar
unknown committed
2428
  keyuse.optimize= 0;
unknown's avatar
unknown committed
2429
  keyuse.keypart_map= 0;
unknown's avatar
unknown committed
2430 2431 2432
  VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
}

2433

unknown's avatar
unknown committed
2434 2435 2436
static int
sort_keyuse(KEYUSE *a,KEYUSE *b)
{
2437
  int res;
unknown's avatar
unknown committed
2438 2439 2440 2441 2442 2443
  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);
2444
  // Place const values before other ones
2445 2446
  if ((res= test((a->used_tables & ~OUTER_REF_TABLE_BIT)) -
       test((b->used_tables & ~OUTER_REF_TABLE_BIT))))
2447 2448 2449 2450
    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
2451 2452 2453 2454
}


/*
2455 2456 2457
  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
2458 2459 2460
*/

static bool
2461
update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
2462 2463
		    uint tables, COND *cond, table_map normal_tables,
		    SELECT_LEX *select_lex)
unknown's avatar
unknown committed
2464 2465
{
  uint	and_level,i,found_eq_constant;
unknown's avatar
unknown committed
2466
  KEY_FIELD *key_fields, *end, *field;
unknown's avatar
unknown committed
2467

2468
  if (!(key_fields=(KEY_FIELD*)
unknown's avatar
merge  
unknown committed
2469
	thd->alloc(sizeof(key_fields[0])*
2470
		   (thd->lex->current_select->cond_count+1)*2)))
2471
    return TRUE; /* purecov: inspected */
unknown's avatar
unknown committed
2472 2473 2474 2475
  and_level= 0;
  field= end= key_fields;
  if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
    return TRUE;
2476
  if (cond)
unknown's avatar
unknown committed
2477
  {
2478
    add_key_fields(join_tab,&end,&and_level,cond,normal_tables);
unknown's avatar
unknown committed
2479
    for (; field != end ; field++)
unknown's avatar
unknown committed
2480
    {
unknown's avatar
unknown committed
2481 2482 2483 2484 2485
      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
2486
    }
unknown's avatar
unknown committed
2487
  }
2488
  for (i=0 ; i < tables ; i++)
unknown's avatar
unknown committed
2489
  {
2490
    if (join_tab[i].on_expr)
unknown's avatar
unknown committed
2491
    {
2492 2493
      add_key_fields(join_tab,&end,&and_level,join_tab[i].on_expr,
		     join_tab[i].table->map);
unknown's avatar
unknown committed
2494 2495
    }
  }
2496
  /* fill keyuse with found key parts */
unknown's avatar
unknown committed
2497
  for ( ; field != end ; field++)
2498
    add_key_part(keyuse,field);
unknown's avatar
unknown committed
2499

2500
  if (select_lex->ftfunc_list->elements)
unknown's avatar
unknown committed
2501 2502 2503 2504 2505
  {
    add_ft_keys(keyuse,join_tab,cond,normal_tables);
  }

  /*
2506
    Special treatment for ft-keys.
2507 2508 2509
    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
2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526
  */
  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)
2527
	use->table->const_key_parts[use->key]|= use->keypart_map;
unknown's avatar
unknown committed
2528 2529
      if (use->keypart != FT_KEYPART)
      {
2530 2531 2532 2533 2534 2535 2536 2537
	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
2538 2539 2540 2541 2542 2543 2544 2545
      }

      *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;
2546
      use->table->reginfo.join_tab->checked_keys.set_bit(use->key);
unknown's avatar
unknown committed
2547 2548 2549 2550 2551 2552 2553 2554 2555
      save_pos++;
    }
    i=(uint) (save_pos-(KEYUSE*) keyuse->buffer);
    VOID(set_dynamic(keyuse,(gptr) &end,i));
    keyuse->elements=i;
  }
  return FALSE;
}

2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574
/*
  Update some values in keyuse for faster find_best_combination() loop
*/

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
2575
    keyuse->ref_table_rows= ~(ha_rows) 0;	// If no ref
2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587
    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);
      }
    }
2588 2589 2590 2591 2592 2593
    /*
      Outer reference (external field) is constant for single executing
      of subquery
    */
    if (keyuse->used_tables == OUTER_REF_TABLE_BIT)
      keyuse->ref_table_rows= 1;
2594 2595 2596
  }
}

unknown's avatar
unknown committed
2597 2598

/*****************************************************************************
2599 2600
  Go through all combinations of not marked tables and find the one
  which uses least records
unknown's avatar
unknown committed
2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614
*****************************************************************************/

/* 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];
2615
  for (;next != table ; pos++)
unknown's avatar
unknown committed
2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638
  {
    JOIN_TAB *tmp=pos[0];
    pos[0]=next;
    next=tmp;
  }
  join->best_ref[idx]=table;
}


static void
find_best_combination(JOIN *join, table_map rest_tables)
{
  DBUG_ENTER("find_best_combination");
  join->best_read=DBL_MAX;
  find_best(join,rest_tables, join->const_tables,1.0,0.0);
  DBUG_VOID_RETURN;
}


static void
find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
	  double read_time)
{
2639
  ha_rows rec;
unknown's avatar
unknown committed
2640
  double tmp;
unknown's avatar
unknown committed
2641
  THD *thd= join->thd;
unknown's avatar
unknown committed
2642 2643 2644 2645 2646 2647 2648 2649

  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 &&
2650 2651
	join->sort_by_table !=
	join->positions[join->const_tables].table->table)
unknown's avatar
unknown committed
2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673
      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;
2674
      uint best_max_key_part=0;
2675
      my_bool found_constraint= 0;
unknown's avatar
unknown committed
2676 2677 2678 2679 2680 2681

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

	/* Test how we can use keys */
2685
	rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE;  // Assumed records/key
unknown's avatar
unknown committed
2686 2687
	for (keyuse=s->keyuse ; keyuse->table == table ;)
	{
2688
	  key_part_map found_part=0;
unknown's avatar
unknown committed
2689 2690 2691 2692
	  table_map found_ref=0;
	  uint key=keyuse->key;
	  KEY *keyinfo=table->key_info+key;
          bool ft_key=(keyuse->keypart == FT_KEYPART);
2693
	  uint found_ref_or_null= 0;
unknown's avatar
unknown committed
2694

2695
	  /* Calculate how many key segments of the current key we can use */
unknown's avatar
unknown committed
2696 2697 2698 2699
	  start_key=keyuse;
	  do
	  {
            uint keypart=keyuse->keypart;
unknown's avatar
unknown committed
2700 2701
            table_map best_part_found_ref= 0;
            double best_prev_record_reads= DBL_MAX;
unknown's avatar
unknown committed
2702 2703
	    do
	    {
2704 2705 2706 2707
	      if (!(rest_tables & keyuse->used_tables) &&
		  !(found_ref_or_null & keyuse->optimize))
	      {
		found_part|=keyuse->keypart_map;
unknown's avatar
unknown committed
2708 2709 2710 2711 2712 2713 2714 2715
                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;
                }
2716 2717
		if (rec > keyuse->ref_table_rows)
		  rec= keyuse->ref_table_rows;
unknown's avatar
unknown committed
2718 2719
		/*
		  If there is one 'key_column IS NULL' expression, we can
2720
		  use this ref_or_null optimisation of this field
unknown's avatar
unknown committed
2721 2722 2723
		*/
		found_ref_or_null|= (keyuse->optimize &
				     KEY_OPTIMIZE_REF_OR_NULL);
unknown's avatar
unknown committed
2724 2725 2726 2727
              }
	      keyuse++;
	    } while (keyuse->table == table && keyuse->key == key &&
		     keyuse->keypart == keypart);
unknown's avatar
unknown committed
2728
	    found_ref|= best_part_found_ref;
unknown's avatar
unknown committed
2729 2730 2731
	  } while (keyuse->table == table && keyuse->key == key);

	  /*
2732
	    Assume that that each key matches a proportional part of table.
unknown's avatar
unknown committed
2733 2734 2735
	  */
          if (!found_part && !ft_key)
	    continue;				// Nothing usable found
2736 2737
	  if (rec < MATCHING_ROWS_IN_OTHER_TABLE)
	    rec= MATCHING_ROWS_IN_OTHER_TABLE;	// Fix for small tables
unknown's avatar
unknown committed
2738 2739

          /*
2740
	    ft-keys require special treatment
unknown's avatar
unknown committed
2741 2742 2743 2744
          */
          if (ft_key)
          {
            /*
2745 2746
	      Really, there should be records=0.0 (yes!)
	      but 1.0 would be probably safer
unknown's avatar
unknown committed
2747 2748 2749 2750 2751 2752
            */
            tmp=prev_record_reads(join,found_ref);
            records=1.0;
          }
          else
          {
2753
	  found_constraint= 1;
unknown's avatar
unknown committed
2754
	  /*
2755
	    Check if we found full key
unknown's avatar
unknown committed
2756
	  */
2757 2758
	  if (found_part == PREV_BITS(uint,keyinfo->key_parts) &&
	      !found_ref_or_null)
unknown's avatar
unknown committed
2759
	  {				/* use eq key */
2760
	    max_key_part= (uint) ~0;
2761 2762
	    if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
				   HA_END_SPACE_KEY)) == HA_NOSAME)
unknown's avatar
unknown committed
2763 2764 2765 2766 2767 2768
	    {
	      tmp=prev_record_reads(join,found_ref);
	      records=1.0;
	    }
	    else
	    {
2769 2770
	      if (!found_ref)
	      {					// We found a const key
2771
		if (table->quick_keys.is_set(key))
unknown's avatar
unknown committed
2772 2773
		  records= (double) table->quick_rows[key];
		else
unknown's avatar
unknown committed
2774 2775 2776 2777
		{
		  /* quick_range couldn't use key! */
		  records= (double) s->records/rec;
		}
unknown's avatar
unknown committed
2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791
	      }
	      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
		}
	      }
2792 2793 2794
	      /* Limit the number of matched rows */
	      tmp= records;
	      set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
2795
	      if (table->used_keys.is_set(key))
unknown's avatar
unknown committed
2796 2797 2798
	      {
		/* we can use only index tree */
		uint keys_per_block= table->file->block_size/2/
unknown's avatar
unknown committed
2799
		  (keyinfo->key_length+table->file->ref_length)+1;
2800
		tmp=record_count*(tmp+keys_per_block-1)/keys_per_block;
unknown's avatar
unknown committed
2801 2802
	      }
	      else
2803
		tmp=record_count*min(tmp,s->worst_seeks);
unknown's avatar
unknown committed
2804 2805 2806 2807 2808
	    }
	  }
	  else
	  {
	    /*
2809 2810 2811
	      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
2812
	    */
2813
	    if ((found_part & 1) &&
2814
		(!(table->file->index_flags(key,0,0) & HA_ONLY_WHOLE_INDEX) ||
2815
		 found_part == PREV_BITS(uint,keyinfo->key_parts)))
unknown's avatar
unknown committed
2816
	    {
2817
	      max_key_part=max_part_bit(found_part);
2818 2819 2820 2821
	      /*
		Check if quick_range could determinate how many rows we
		will match
	      */
2822
	      if (table->quick_keys.is_set(key) &&
2823
		  table->quick_key_parts[key] == max_key_part)
unknown's avatar
unknown committed
2824 2825 2826 2827 2828 2829 2830 2831 2832
		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
		{
		  /*
2833
		    Assume that the first key part matches 1% of the file
2834
		    and that the hole key matches 10 (duplicates) or 1
2835 2836 2837 2838 2839
		    (unique) records.
		    Assume also that more key matches proportionally more
		    records
		    This gives the formula:
		    records= (x * (b-a) + a*c-b)/(c-1)
2840

2841 2842 2843 2844
		    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
2845 2846
		  */
		  double rec_per_key;
2847 2848 2849
                  rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1] ?
		    (double) keyinfo->rec_per_key[keyinfo->key_parts-1] :
		    (double) s->records/rec+1;   
unknown's avatar
unknown committed
2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863
		  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;
		}
2864 2865 2866 2867
		/*
		  If quick_select was used on a part of this key, we know
		  the maximum number of rows that the key can match.
		*/
unknown's avatar
unknown committed
2868
		if (table->quick_keys.is_set(key) &&
2869 2870 2871
		    table->quick_key_parts[key] <= max_key_part &&
		    records > (double) table->quick_rows[key])
		  tmp= records= (double) table->quick_rows[key];
unknown's avatar
unknown committed
2872
		else if (found_ref_or_null)
2873 2874 2875 2876 2877
		{
		  /* We need to do two key searches to find key */
		  tmp*= 2.0;
		  records*= 2.0;
		}
unknown's avatar
unknown committed
2878
	      }
2879 2880
	      /* Limit the number of matched rows */
	      set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
2881
	      if (table->used_keys.is_set(key))
unknown's avatar
unknown committed
2882 2883 2884
	      {
		/* we can use only index tree */
		uint keys_per_block= table->file->block_size/2/
unknown's avatar
unknown committed
2885
		  (keyinfo->key_length+table->file->ref_length)+1;
unknown's avatar
unknown committed
2886 2887 2888 2889 2890 2891 2892 2893
		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
	  }
2894
          } /* not ft_key */
unknown's avatar
unknown committed
2895 2896 2897 2898 2899 2900
	  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;
2901
	    best_max_key_part=max_key_part;
unknown's avatar
unknown committed
2902 2903 2904 2905
	  }
	}
	records=best_records;
      }
2906 2907 2908 2909

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

	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.
2915 2916 2917
      */
      if ((records >= s->found_records || best > s->read_time) &&
	  !(s->quick && best_key && s->quick->index == best_key->key &&
2918
	    best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
2919
	  !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
2920
	    ! s->table->used_keys.is_clear_all() && best_key) &&
2921
	  !(s->table->force_index && best_key))
unknown's avatar
unknown committed
2922
      {						// Check full join
2923 2924 2925 2926 2927 2928 2929 2930 2931 2932
        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;

2933 2934 2935 2936 2937 2938
        /*
          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)
2939
        {
2940 2941 2942 2943 2944
          /*
            For each record we:
             - read record range through 'quick'
             - skip rows which does not satisfy WHERE constraints
           */
2945
          tmp= record_count *
2946 2947
               (s->quick->read_time +
               (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE);
2948 2949 2950
        }
        else
        {
2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978
          /* Estimate cost of reading table. */
          tmp= s->table->file->scan_time();
          if (s->on_expr)                         // Can't use join cache
          {
            /*
              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;
          }
2979
        }
2980

2981
        /*
2982
          We estimate the cost of evaluating WHERE clause for found records
2983
          as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus
2984
          tmp give us total cost of using TABLE SCAN
unknown's avatar
unknown committed
2985
        */
unknown's avatar
unknown committed
2986
	if (best == DBL_MAX ||
2987
	    (tmp  + record_count/(double) TIME_FOR_COMPARE*rnd_records <
unknown's avatar
unknown committed
2988 2989
	     best + record_count/(double) TIME_FOR_COMPARE*records))
	{
2990 2991 2992 2993
	  /*
	    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
2994
	  best=tmp;
2995
	  records= rows2double(rnd_records);
unknown's avatar
unknown committed
2996 2997 2998
	  best_key=0;
	}
      }
2999
      join->positions[idx].records_read= records;
unknown's avatar
unknown committed
3000 3001 3002
      join->positions[idx].key=best_key;
      join->positions[idx].table= s;
      if (!best_key && idx == join->const_tables &&
unknown's avatar
unknown committed
3003
	  s->table == join->sort_by_table &&
3004
	  join->unit->select_limit_cnt >= records)
unknown's avatar
unknown committed
3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023
	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;
	}
3024
	swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
unknown's avatar
unknown committed
3025 3026
	find_best(join,rest_tables & ~real_table_bit,idx+1,
		  current_record_count,current_read_time);
unknown's avatar
unknown committed
3027 3028
        if (thd->killed)
          return;
3029
	swap_variables(JOIN_TAB*, join->best_ref[idx], *pos);
unknown's avatar
unknown committed
3030 3031 3032 3033 3034 3035 3036 3037 3038
      }
      if (join->select_options & SELECT_STRAIGHT_JOIN)
	break;				// Don't test all combinations
    }
  }
}


/*
3039
  Find how much space the prevous read not const tables takes in cache
unknown's avatar
unknown committed
3040 3041
*/

3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076
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
3077 3078 3079
static uint
cache_record_length(JOIN *join,uint idx)
{
3080
  uint length=0;
unknown's avatar
unknown committed
3081
  JOIN_TAB **pos,**end;
3082
  THD *thd=join->thd;
unknown's avatar
unknown committed
3083 3084 3085 3086 3087 3088

  for (pos=join->best_ref+join->const_tables,end=join->best_ref+idx ;
       pos != end ;
       pos++)
  {
    JOIN_TAB *join_tab= *pos;
3089 3090
    if (!join_tab->used_fieldlength)		/* Not calced yet */
      calc_used_field_length(thd, join_tab);
unknown's avatar
unknown committed
3091 3092 3093 3094 3095 3096 3097 3098 3099 3100
    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
3101
  found_ref&= ~OUTER_REF_TABLE_BIT;
unknown's avatar
unknown committed
3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114
  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;
}


/*****************************************************************************
3115
  Set up join struct according to best position.
unknown's avatar
unknown committed
3116 3117 3118 3119 3120
*****************************************************************************/

static bool
get_best_combination(JOIN *join)
{
3121
  uint i,tablenr;
unknown's avatar
unknown committed
3122 3123 3124 3125
  table_map used_tables;
  JOIN_TAB *join_tab,*j;
  KEYUSE *keyuse;
  uint table_count;
3126
  THD *thd=join->thd;
unknown's avatar
unknown committed
3127 3128 3129

  table_count=join->tables;
  if (!(join->join_tab=join_tab=
3130
	(JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*table_count)))
unknown's avatar
unknown committed
3131 3132 3133 3134
    return TRUE;

  join->full_join=0;

unknown's avatar
unknown committed
3135
  used_tables= OUTER_REF_TABLE_BIT;		// Outer row is already read
unknown's avatar
unknown committed
3136 3137 3138 3139 3140 3141 3142 3143 3144
  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;
    if (!j->on_expr)
      form->reginfo.not_exists_optimize=0;	// Only with LEFT JOIN
3145 3146 3147 3148 3149
    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
3150 3151 3152

    if (j->type == JT_SYSTEM)
      continue;
3153
    if (j->keys.is_clear_all() || !(keyuse= join->best_positions[tablenr].key))
unknown's avatar
unknown committed
3154 3155 3156 3157 3158
    {
      j->type=JT_ALL;
      if (tablenr != join->const_tables)
	join->full_join=1;
    }
3159 3160 3161
    else if (create_ref_for_key(join, j, keyuse, used_tables))
      return TRUE;				// Something went wrong
  }
unknown's avatar
unknown committed
3162

3163 3164 3165 3166 3167
  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;
}
3168

unknown's avatar
unknown committed
3169

3170 3171 3172 3173 3174 3175 3176 3177 3178
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;
3179

3180
  /*  Use best key from find_best */
3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195
  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;
3196 3197 3198 3199 3200 3201
    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
    */
3202 3203
    do
    {
3204
      if (!(~used_tables & keyuse->used_tables))
unknown's avatar
unknown committed
3205
      {
3206 3207
	if (keyparts == keyuse->keypart &&
	    !(found_part_ref_or_null & keyuse->optimize))
unknown's avatar
unknown committed
3208
	{
3209
	  keyparts++;
3210 3211
	  length+= keyinfo->key_part[keyuse->keypart].store_length;
	  found_part_ref_or_null|= keyuse->optimize;
unknown's avatar
unknown committed
3212 3213
	}
      }
3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233
      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;

3234 3235
  store_key **ref_key= j->ref.key_copy;
  byte *key_buff=j->ref.key_buff, *null_ref_key= 0;
3236
  bool keyuse_uses_no_tables= TRUE;
3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255
  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
3256
      keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables;
3257 3258 3259
      if (!keyuse->used_tables &&
	  !(join->select_options & SELECT_DESCRIBE))
      {					// Compare against constant
unknown's avatar
unknown committed
3260 3261 3262 3263
	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);
3264
	if (thd->is_fatal_error)
3265
	  return TRUE;
unknown's avatar
unknown committed
3266
	tmp.copy();
unknown's avatar
unknown committed
3267 3268
      }
      else
3269 3270 3271 3272
	*ref_key++= get_store_key(thd,
				  keyuse,join->const_table_map,
				  &keyinfo->key_part[i],
				  (char*) key_buff,maybe_null);
3273
      /*
unknown's avatar
unknown committed
3274
	Remeber if we are going to use REF_OR_NULL
3275 3276 3277
	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
      */
unknown's avatar
unknown committed
3278
      if ((keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL) && maybe_null)
3279
	null_ref_key= key_buff;
3280
      key_buff+=keyinfo->key_part[i].store_length;
unknown's avatar
unknown committed
3281
    }
3282 3283
  } /* not ftkey */
  *ref_key=0;				// end_marker
3284 3285 3286 3287
  if (j->type == JT_FT)
    return 0;
  if (j->type == JT_CONST)
    j->table->const_table= 1;
3288
  else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
unknown's avatar
unknown committed
3289
			       HA_END_SPACE_KEY)) != HA_NOSAME) ||
unknown's avatar
unknown committed
3290
	   keyparts != keyinfo->key_parts || null_ref_key)
3291 3292 3293
  {
    /* Must read with repeat */
    j->type= null_ref_key ? JT_REF_OR_NULL : JT_REF;
3294
    j->ref.null_ref_key= null_ref_key;
3295
  }
unknown's avatar
unknown committed
3296
  else if (keyuse_uses_no_tables)
3297
  {
3298 3299 3300 3301 3302 3303 3304 3305
    /*
      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
3306
  }
3307 3308
  else
    j->type=JT_EQ_REF;
unknown's avatar
unknown committed
3309 3310 3311 3312
  return 0;
}


3313

unknown's avatar
unknown committed
3314
static store_key *
unknown's avatar
unknown committed
3315 3316
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
3317 3318 3319
{
  if (!((~used_tables) & keyuse->used_tables))		// if const item
  {
unknown's avatar
unknown committed
3320 3321
    return new store_key_const_item(thd,
				    key_part->field,
unknown's avatar
unknown committed
3322 3323 3324 3325 3326 3327
				    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
3328 3329
    return new store_key_field(thd,
			       key_part->field,
unknown's avatar
unknown committed
3330 3331 3332 3333 3334
			       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
3335 3336
  return new store_key_item(thd,
			    key_part->field,
unknown's avatar
unknown committed
3337 3338 3339 3340 3341 3342 3343
			    key_buff + maybe_null,
			    maybe_null ? key_buff : 0,
			    key_part->length,
			    keyuse->val);
}

/*
3344 3345
  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
3346 3347 3348 3349 3350
*/

bool
store_val_in_field(Field *field,Item *item)
{
3351
  bool error;
unknown's avatar
unknown committed
3352
  THD *thd=current_thd;
3353
  ha_rows cuted_fields=thd->cuted_fields;
3354 3355 3356 3357 3358
  /*
    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
   */
unknown's avatar
unknown committed
3359
  enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
3360
  thd->count_cuted_fields= CHECK_FIELD_WARN;
3361
  error= item->save_in_field(field, 1);
3362
  thd->count_cuted_fields= old_count_cuted_fields;
3363
  return error || cuted_fields != thd->cuted_fields;
unknown's avatar
unknown committed
3364 3365 3366 3367 3368 3369 3370 3371 3372
}


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

3373 3374
  if (!(tableptr=(TABLE**) join->thd->alloc(sizeof(TABLE*))) ||
      !(join_tab=(JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
unknown's avatar
unknown committed
3375 3376 3377 3378 3379 3380
    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
3381 3382 3383
  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
3384
  join->first_record=join->sort_and_group=0;
unknown's avatar
unknown committed
3385
  join->send_records=(ha_rows) 0;
unknown's avatar
unknown committed
3386
  join->group=0;
unknown's avatar
unknown committed
3387
  join->row_limit=join->unit->select_limit_cnt;
unknown's avatar
unknown committed
3388
  join->do_send_rows = (join->row_limit) ? 1 : 0;
unknown's avatar
unknown committed
3389

unknown's avatar
unknown committed
3390
  join_tab->cache.buff=0;			/* No caching */
unknown's avatar
unknown committed
3391 3392 3393 3394 3395
  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
3396
  join_tab->keys.init(~0);                      /* test everything in quick */
unknown's avatar
unknown committed
3397 3398 3399
  join_tab->info=0;
  join_tab->on_expr=0;
  join_tab->ref.key = -1;
unknown's avatar
unknown committed
3400 3401
  join_tab->not_used_in_distinct=0;
  join_tab->read_first_record= join_init_read_record;
3402
  join_tab->join=join;
unknown's avatar
unknown committed
3403
  bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
unknown's avatar
unknown committed
3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418
  tmp_table->status=0;
  tmp_table->null_row=0;
  return FALSE;
}


static bool
make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
{
  DBUG_ENTER("make_join_select");
  if (select)
  {
    table_map used_tables;
    if (join->tables > 1)
      cond->update_used_tables();		// Tablenr may have changed
3419 3420 3421
    if (join->const_tables == join->tables &&
	join->thd->lex->current_select->master_unit() ==
	&join->thd->lex->unit)		// not upper level SELECT
3422
      join->const_table_map|=RAND_TABLE_BIT;
unknown's avatar
unknown committed
3423 3424 3425 3426 3427
    {						// Check const tables
      COND *const_cond=
	make_cond_for_table(cond,join->const_table_map,(table_map) 0);
      DBUG_EXECUTE("where",print_where(const_cond,"constants"););
      if (const_cond && !const_cond->val_int())
3428 3429
      {
	DBUG_PRINT("info",("Found impossible WHERE condition"));
unknown's avatar
unknown committed
3430
	DBUG_RETURN(1);				// Impossible const condition
3431
      }
unknown's avatar
unknown committed
3432
    }
unknown's avatar
unknown committed
3433 3434
    used_tables=((select->const_tables=join->const_table_map) |
		 OUTER_REF_TABLE_BIT | RAND_TABLE_BIT);
unknown's avatar
unknown committed
3435 3436 3437 3438
    for (uint i=join->const_tables ; i < join->tables ; i++)
    {
      JOIN_TAB *tab=join->join_tab+i;
      table_map current_map= tab->table->map;
unknown's avatar
unknown committed
3439 3440 3441 3442
      /*
	Following force including random expression in last table condition.
	It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
      */
3443
      if (i == join->tables-1)
unknown's avatar
unknown committed
3444
	current_map|= OUTER_REF_TABLE_BIT | RAND_TABLE_BIT;
3445
      bool use_quick_range=0;
unknown's avatar
unknown committed
3446
      used_tables|=current_map;
3447 3448

      if (tab->type == JT_REF && tab->quick &&
unknown's avatar
unknown committed
3449
	  (uint) tab->ref.key == tab->quick->index &&
3450 3451 3452 3453 3454 3455
	  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;
3456
        tab->ref.key= -1;
3457
	tab->ref.key_parts=0;		// Don't use ref key.
3458
	join->best_positions[i].records_read= rows2double(tab->quick->records);
3459 3460
      }

unknown's avatar
unknown committed
3461
      COND *tmp=make_cond_for_table(cond,used_tables,current_map);
3462 3463 3464 3465 3466 3467 3468 3469
      if (!tmp && tab->quick)
      {						// Outer join
	/*
	  Hack to handle the case where we only refer to a table
	  in the ON part of an OUTER JOIN.
	*/
	tmp=new Item_int((longlong) 1,1);	// Always true
      }
unknown's avatar
unknown committed
3470 3471 3472 3473
      if (tmp)
      {
	DBUG_EXECUTE("where",print_where(tmp,tab->table->table_name););
	SQL_SELECT *sel=tab->select=(SQL_SELECT*)
3474
	  join->thd->memdup((gptr) select, sizeof(SQL_SELECT));
unknown's avatar
unknown committed
3475 3476 3477 3478 3479 3480
	if (!sel)
	  DBUG_RETURN(1);			// End of memory
	tab->select_cond=sel->cond=tmp;
	sel->head=tab->table;
	if (tab->quick)
	{
3481 3482
	  /* Use quick key read if it's a constant and it's not used
	     with key reading */
3483
	  if (tab->needed_reg.is_clear_all() && tab->type != JT_EQ_REF
3484
	      && tab->type != JT_FT && (tab->type != JT_REF ||
unknown's avatar
unknown committed
3485 3486 3487
	       (uint) tab->ref.key == tab->quick->index))
	  {
	    sel->quick=tab->quick;		// Use value from get_quick_...
3488 3489
	    sel->quick_keys.clear_all();
	    sel->needed_reg.clear_all();
unknown's avatar
unknown committed
3490 3491 3492 3493 3494 3495 3496 3497 3498 3499
	  }
	  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)
	{
3500 3501
	  if (!tab->const_keys.is_clear_all() &&
              tab->table->reginfo.impossible_range)
unknown's avatar
unknown committed
3502 3503
	    DBUG_RETURN(1);
	}
3504
	else if (tab->type == JT_ALL && ! use_quick_range)
unknown's avatar
unknown committed
3505
	{
3506
	  if (!tab->const_keys.is_clear_all() &&
unknown's avatar
unknown committed
3507 3508 3509 3510
	      tab->table->reginfo.impossible_range)
	    DBUG_RETURN(1);				// Impossible range
	  /*
	    We plan to scan all rows.
3511 3512 3513
	    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
3514 3515
	  */

3516 3517 3518
	  if ((!tab->keys.is_subset(tab->const_keys) && i > 0) ||
	      (!tab->const_keys.is_clear_all() && i == join->const_tables &&
	       join->unit->select_limit_cnt <
3519
	       join->best_positions[i].records_read &&
3520
	       !(join->select_options & OPTION_FOUND_ROWS)))
unknown's avatar
unknown committed
3521
	  {
3522 3523
	    /* Join with outer join condition */
	    COND *orig_cond=sel->cond;
unknown's avatar
unknown committed
3524
	    sel->cond= and_conds(sel->cond, tab->on_expr);
3525 3526 3527 3528 3529 3530 3531 3532

	    /*
              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
unknown committed
3533
	    if (sel->cond && !sel->cond->fixed)
3534 3535
	      sel->cond->quick_fix_field();

3536
	    if (sel->test_quick_select(join->thd, tab->keys,
unknown's avatar
unknown committed
3537
				       used_tables & ~ current_map,
3538 3539 3540
				       (join->select_options &
					OPTION_FOUND_ROWS ?
					HA_POS_ERROR :
3541
					join->unit->select_limit_cnt)) < 0)
unknown's avatar
unknown committed
3542 3543 3544 3545 3546
            {
	      /*
		Before reporting "Impossible WHERE" for the whole query
		we have to check isn't it only "impossible ON" instead
	      */
3547 3548
              sel->cond=orig_cond;
              if (!tab->on_expr ||
3549
                  sel->test_quick_select(join->thd, tab->keys,
3550 3551 3552 3553
                                         used_tables & ~ current_map,
                                         (join->select_options &
                                          OPTION_FOUND_ROWS ?
                                          HA_POS_ERROR :
unknown's avatar
unknown committed
3554 3555
                                          join->unit->select_limit_cnt)) < 0)
		DBUG_RETURN(1);			// Impossible WHERE
3556 3557 3558 3559
            }
            else
	      sel->cond=orig_cond;

3560 3561 3562
	    /* Fix for EXPLAIN */
	    if (sel->quick)
	      join->best_positions[i].records_read= sel->quick->records;
unknown's avatar
unknown committed
3563 3564 3565 3566
	  }
	  else
	  {
	    sel->needed_reg=tab->needed_reg;
3567
	    sel->quick_keys.clear_all();
unknown's avatar
unknown committed
3568
	  }
3569 3570
	  if (!sel->quick_keys.is_subset(tab->checked_keys) ||
              !sel->needed_reg.is_subset(tab->checked_keys))
unknown's avatar
unknown committed
3571
	  {
3572 3573 3574 3575
	    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
3576 3577 3578
			      (select->quick &&
			       (select->quick->records >= 100L)))) ?
	      2 : 1;
unknown's avatar
unknown committed
3579
	    sel->read_tables= used_tables & ~current_map;
unknown's avatar
unknown committed
3580 3581 3582 3583 3584 3585 3586 3587 3588
	  }
	  if (i != join->const_tables && tab->use_quick != 2)
	  {					/* Read with cache */
	    if ((tmp=make_cond_for_table(cond,
					 join->const_table_map |
					 current_map,
					 current_map)))
	    {
	      DBUG_EXECUTE("where",print_where(tmp,"cache"););
3589 3590
	      tab->cache.select=(SQL_SELECT*)
		join->thd->memdup((gptr) sel, sizeof(SQL_SELECT));
unknown's avatar
unknown committed
3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603
	      tab->cache.select->cond=tmp;
	      tab->cache.select->read_tables=join->const_table_map;
	    }
	  }
	}
      }
    }
  }
  DBUG_RETURN(0);
}


static void
3604
make_join_readinfo(JOIN *join, uint options)
unknown's avatar
unknown committed
3605 3606
{
  uint i;
3607
  bool statistics= test(!(join->select_options & SELECT_DESCRIBE));
unknown's avatar
unknown committed
3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626
  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;
3627
      if (table->used_keys.is_set(tab->ref.key) &&
3628 3629 3630 3631 3632
          !table->no_keyread)
      {
        table->key_read=1;
        table->file->extra(HA_EXTRA_KEYREAD);
      }
unknown's avatar
unknown committed
3633 3634 3635
      break;
    case JT_EQ_REF:
      table->status=STATUS_NO_RECORD;
3636 3637 3638 3639 3640
      if (tab->select)
      {
	delete tab->select->quick;
	tab->select->quick=0;
      }
unknown's avatar
unknown committed
3641 3642 3643 3644
      delete tab->quick;
      tab->quick=0;
      tab->read_first_record= join_read_key;
      tab->read_record.read_record= join_no_more_records;
3645
      if (table->used_keys.is_set(tab->ref.key) &&
unknown's avatar
unknown committed
3646
	  !table->no_keyread)
unknown's avatar
unknown committed
3647 3648 3649 3650 3651
      {
	table->key_read=1;
	table->file->extra(HA_EXTRA_KEYREAD);
      }
      break;
3652
    case JT_REF_OR_NULL:
unknown's avatar
unknown committed
3653 3654
    case JT_REF:
      table->status=STATUS_NO_RECORD;
3655 3656 3657 3658 3659
      if (tab->select)
      {
	delete tab->select->quick;
	tab->select->quick=0;
      }
unknown's avatar
unknown committed
3660 3661
      delete tab->quick;
      tab->quick=0;
3662
      if (table->used_keys.is_set(tab->ref.key) &&
unknown's avatar
unknown committed
3663
	  !table->no_keyread)
unknown's avatar
unknown committed
3664 3665 3666 3667
      {
	table->key_read=1;
	table->file->extra(HA_EXTRA_KEYREAD);
      }
3668 3669 3670 3671 3672 3673 3674 3675 3676 3677
      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
3678 3679 3680 3681 3682 3683 3684 3685
      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:
      /*
3686
	If previous table use cache
unknown's avatar
unknown committed
3687 3688
      */
      table->status=STATUS_NO_RECORD;
unknown's avatar
unknown committed
3689
      if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
unknown's avatar
unknown committed
3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700
	  tab->use_quick != 2 && !tab->on_expr)
      {
	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)
3701
      {
3702
	join->thd->server_status|=SERVER_QUERY_NO_GOOD_INDEX_USED;
unknown's avatar
unknown committed
3703
	tab->read_first_record= join_init_quick_read_record;
3704 3705
	if (statistics)
	  statistic_increment(select_range_check_count, &LOCK_status);
3706
      }
unknown's avatar
unknown committed
3707 3708 3709
      else
      {
	tab->read_first_record= join_init_read_record;
3710 3711 3712 3713
	if (i == join->const_tables)
	{
	  if (tab->select && tab->select->quick)
	  {
3714 3715
	    if (statistics)
	      statistic_increment(select_range_count, &LOCK_status);
3716 3717 3718
	  }
	  else
	  {
3719
	    join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
3720 3721
	    if (statistics)
	      statistic_increment(select_scan_count, &LOCK_status);
3722 3723 3724 3725 3726 3727
	  }
	}
	else
	{
	  if (tab->select && tab->select->quick)
	  {
3728 3729
	    if (statistics)
	      statistic_increment(select_full_range_join_count, &LOCK_status);
3730 3731 3732
	  }
	  else
	  {
3733
	    join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
3734 3735
	    if (statistics)
	      statistic_increment(select_full_join_count, &LOCK_status);
3736 3737
	  }
	}
unknown's avatar
unknown committed
3738
	if (!table->no_keyread)
unknown's avatar
unknown committed
3739
	{
unknown's avatar
unknown committed
3740
	  if (tab->select && tab->select->quick &&
3741
	      table->used_keys.is_set(tab->select->quick->index))
unknown's avatar
unknown committed
3742 3743 3744 3745
	  {
	    table->key_read=1;
	    table->file->extra(HA_EXTRA_KEYREAD);
	  }
3746 3747
	  else if (!table->used_keys.is_clear_all() &&
		   !(tab->select && tab->select->quick))
unknown's avatar
unknown committed
3748
	  {					// Only read index tree
unknown's avatar
unknown committed
3749
	    tab->index=find_shortest_key(table, & table->used_keys);
3750
	    tab->read_first_record= join_read_first;
unknown's avatar
unknown committed
3751 3752
	    tab->type=JT_NEXT;		// Read with index_first / index_next
	  }
unknown's avatar
unknown committed
3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768
	}
      }
      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
3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790
/*
  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++)
  {
3791
    if (tab->type == JT_ALL && (!tab->select || !tab->select->quick))
unknown's avatar
unknown committed
3792 3793 3794 3795 3796 3797 3798 3799 3800
    {
      my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,MYF(0));
      return(1);
    }
  }
  return(0);
}


3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822
/*
  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
3823
    table->file->ha_index_or_rnd_end();
3824 3825 3826 3827 3828 3829 3830 3831 3832 3833
    /*
      We need to reset this for next select
      (Tested in part_of_refkey)
    */
    table->reginfo.join_tab= 0;
  }
  end_read_record(&read_record);
}


3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846
/*
  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
3847 3848
{
  JOIN_TAB *tab,*end;
unknown's avatar
unknown committed
3849
  DBUG_ENTER("JOIN::join_free");
unknown's avatar
unknown committed
3850

3851
  full= full || (!select_lex->uncacheable &&
3852
                 !thd->lex->subqueries &&
3853
                 !thd->lex->describe); // do not cleanup too early on EXPLAIN
3854

3855
  if (table)
unknown's avatar
unknown committed
3856
  {
3857 3858 3859 3860
    /*
      Only a sorted table may be cached.  This sorted table is always the
      first non const table in join->table
    */
3861
    if (tables > const_tables) // Test for not-const tables
unknown's avatar
unknown committed
3862
    {
3863 3864
      free_io_cache(table[const_tables]);
      filesort_free_buffers(table[const_tables]);
unknown's avatar
unknown committed
3865
    }
3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877

    for (SELECT_LEX_UNIT *unit= select_lex->first_inner_unit(); unit;
         unit= unit->next_unit())
    {
      JOIN *join;
      for (SELECT_LEX *sl= unit->first_select_in_union(); sl;
           sl= sl->next_select())
        if ((join= sl->join))
          join->join_free(full);
    }

    if (full)
unknown's avatar
unknown committed
3878 3879 3880 3881
    {
      for (tab= join_tab, end= tab+tables; tab != end; tab++)
	tab->cleanup();
      table= 0;
3882
      tables= 0;
unknown's avatar
unknown committed
3883 3884
    }
    else
3885
    {
3886
      for (tab= join_tab, end= tab+tables; tab != end; tab++)
unknown's avatar
unknown committed
3887
      {
3888 3889
	if (tab->table)
	    tab->table->file->ha_index_or_rnd_end();
unknown's avatar
unknown committed
3890
      }
3891
    }
unknown's avatar
unknown committed
3892
  }
3893

3894 3895 3896 3897
  /*
    We are not using tables anymore
    Unlock all tables. We may be in an INSERT .... SELECT statement.
  */
unknown's avatar
unknown committed
3898
  if (full && lock && thd->lock && !(select_options & SELECT_NO_UNLOCK) &&
3899
      !select_lex->subquery_in_having)
unknown's avatar
unknown committed
3900
  {
3901 3902 3903 3904 3905 3906 3907
    // 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
3908
  }
3909

3910 3911
  if (full)
  {
3912
    group_fields.delete_elements();
3913 3914 3915 3916 3917
    /*
      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.
    */
    tmp_table_param.copy_funcs.empty();
3918
    tmp_table_param.cleanup();
3919
  }
unknown's avatar
unknown committed
3920
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
3921 3922 3923 3924
}


/*****************************************************************************
3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937
  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
3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961
*****************************************************************************/

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)
      {
3962
	if ((*ref_item)->eq(order->item[0],0))
unknown's avatar
unknown committed
3963 3964 3965 3966 3967
	  break;
      }
      if (order)
      {
	found++;
unknown's avatar
unknown committed
3968
	DBUG_ASSERT(!(order->used & map));
unknown's avatar
unknown committed
3969 3970 3971 3972 3973 3974 3975 3976
	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 */
3977
  for (; found && start_order ; start_order=start_order->next)
unknown's avatar
unknown committed
3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994
  {
    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)
3995
    return 0;			// skip this optimize /* purecov: inspected */
unknown's avatar
unknown committed
3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010
  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;

4011
  for (; join_tab != end ; join_tab++)
unknown's avatar
unknown committed
4012 4013 4014 4015 4016 4017 4018
  {
    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
4019
    ref->depend_map=depend_map & ~OUTER_REF_TABLE_BIT;
4020
    depend_map&= ~OUTER_REF_TABLE_BIT;
4021
    for (JOIN_TAB **tab=join->map2table;
unknown's avatar
unknown committed
4022
	 depend_map ;
4023
	 tab++,depend_map>>=1 )
unknown's avatar
unknown committed
4024 4025
    {
      if (depend_map & 1)
4026
	ref->depend_map|=(*tab)->ref.depend_map;
unknown's avatar
unknown committed
4027 4028 4029 4030 4031 4032 4033 4034 4035
    }
  }
}


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

static void update_depend_map(JOIN *join, ORDER *order)
{
4036
  for (; order ; order=order->next)
unknown's avatar
unknown committed
4037 4038 4039 4040
  {
    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
4041 4042
    // 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
4043
    {
4044
      for (JOIN_TAB **tab=join->map2table;
unknown's avatar
unknown committed
4045
	   depend_map ;
4046
	   tab++, depend_map>>=1)
unknown's avatar
unknown committed
4047 4048
      {
	if (depend_map & 1)
4049
	  order->depend_map|=(*tab)->ref.depend_map;
unknown's avatar
unknown committed
4050 4051 4052 4053 4054 4055 4056
      }
    }
  }
}


/*
unknown's avatar
unknown committed
4057 4058
  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
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
*/

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;
  *simple_order= join->join_tab[join->const_tables].on_expr ? 0 : 1;

  /* 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
4085
      continue;					// skip const item
unknown's avatar
unknown committed
4086 4087 4088
    }
    else
    {
unknown's avatar
unknown committed
4089
      if (order_tables & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT))
unknown's avatar
unknown committed
4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100
	*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)))
	{
unknown's avatar
unknown committed
4101
	  if (!(order_tables & first_table) && only_eq_ref_tables(join,first_order,ref))
unknown's avatar
unknown committed
4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119
	  {
	    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);
}

4120

unknown's avatar
unknown committed
4121
static int
4122 4123
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
4124 4125
		 const char *info, Item *having, Procedure *procedure,
		 SELECT_LEX_UNIT *unit)
unknown's avatar
unknown committed
4126 4127 4128 4129
{
  DBUG_ENTER("return_zero_rows");

  if (select_options & SELECT_DESCRIBE)
4130
  {
unknown's avatar
unknown committed
4131
    select_describe(join, FALSE, FALSE, FALSE, info);
unknown's avatar
unknown committed
4132 4133
    DBUG_RETURN(0);
  }
unknown's avatar
unknown committed
4134

4135 4136
  join->join_free(0);

unknown's avatar
unknown committed
4137 4138 4139 4140
  if (send_row)
  {
    for (TABLE_LIST *table=tables; table ; table=table->next)
      mark_as_null_row(table->table);		// All fields are NULL
4141
    if (having && having->val_int() == 0)
unknown's avatar
unknown committed
4142 4143
      send_row=0;
  }
4144
  if (!(result->send_fields(fields,1)))
unknown's avatar
unknown committed
4145 4146
  {
    if (send_row)
unknown's avatar
unknown committed
4147 4148 4149 4150 4151
    {
      List_iterator_fast<Item> it(fields);
      Item *item;
      while ((item= it++))
	item->no_rows_in_result();
unknown's avatar
unknown committed
4152
      result->send_data(fields);
unknown's avatar
unknown committed
4153
    }
4154
    result->send_eof();				// Should be safe
unknown's avatar
unknown committed
4155
  }
4156 4157
  /* Update results for FOUND_ROWS */
  join->thd->limit_found_rows= join->thd->examined_row_count= 0;
unknown's avatar
unknown committed
4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168
  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
}

/*****************************************************************************
4169 4170 4171 4172 4173 4174
  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
4175 4176 4177 4178
*****************************************************************************/

class COND_CMP :public ilink {
public:
unknown's avatar
unknown committed
4179
  static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
unknown's avatar
unknown committed
4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195
  static void operator delete(void *ptr __attribute__((unused)),
			      size_t size __attribute__((unused))) {} /*lint -e715 */

  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

/*
4196 4197
  change field = field to field = const for each found field = const in the
  and_level
unknown's avatar
unknown committed
4198 4199 4200
*/

static void
4201 4202 4203
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
4204 4205 4206 4207 4208 4209 4210 4211
{
  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++))
4212
      change_cond_ref_to_const(thd, save_list,and_level ? cond : item, item,
unknown's avatar
unknown committed
4213 4214 4215 4216 4217 4218 4219
			       field, value);
    return;
  }
  if (cond->eq_cmp_result() == Item::COND_OK)
    return;					// Not a boolean function

  Item_bool_func2 *func=  (Item_bool_func2*) cond;
4220 4221 4222
  Item **args= func->arguments();
  Item *left_item=  args[0];
  Item *right_item= args[1];
unknown's avatar
unknown committed
4223 4224
  Item_func::Functype functype=  func->functype();

4225 4226 4227 4228
  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
4229 4230 4231 4232
  {
    Item *tmp=value->new_item();
    if (tmp)
    {
unknown's avatar
unknown committed
4233 4234
      tmp->collation.set(value->collation.collation,
                         value->collation.derivation);
4235
      thd->change_item_tree(args + 1, tmp);
unknown's avatar
unknown committed
4236 4237 4238 4239 4240 4241 4242 4243 4244
      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);
      }
4245
      func->set_cmp_func();
unknown's avatar
unknown committed
4246 4247
    }
  }
4248 4249 4250 4251
  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
4252 4253 4254 4255
  {
    Item *tmp=value->new_item();
    if (tmp)
    {
unknown's avatar
unknown committed
4256 4257
      tmp->collation.set(value->collation.collation,
                         value->collation.derivation);
4258 4259
      thd->change_item_tree(args, tmp);
      value= tmp;
unknown's avatar
unknown committed
4260 4261 4262 4263
      func->update_used_tables();
      if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC)
	  && and_father != cond && !right_item->const_item())
      {
4264
        args[0]= args[1];                       // For easy check
4265
        thd->change_item_tree(args + 1, value);
unknown's avatar
unknown committed
4266 4267 4268 4269 4270
	cond->marker=1;
	COND_CMP *tmp2;
	if ((tmp2=new COND_CMP(and_father,func)))
	  save_list->push_back(tmp2);
      }
4271
      func->set_cmp_func();
unknown's avatar
unknown committed
4272 4273 4274 4275
    }
  }
}

4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308
/*
  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
4309 4310

static void
4311 4312
propagate_cond_constants(THD *thd, I_List<COND_CMP> *save_list,
                         COND *and_father, COND *cond)
unknown's avatar
unknown committed
4313 4314 4315 4316 4317
{
  if (cond->type() == Item::COND_ITEM)
  {
    bool and_level= ((Item_cond*) cond)->functype() ==
      Item_func::COND_AND_FUNC;
unknown's avatar
unknown committed
4318
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
4319 4320 4321 4322
    Item *item;
    I_List<COND_CMP> save;
    while ((item=li++))
    {
4323
      propagate_cond_constants(thd, &save,and_level ? cond : item, item);
unknown's avatar
unknown committed
4324 4325 4326 4327 4328 4329
    }
    if (and_level)
    {						// Handle other found items
      I_List_iterator<COND_CMP> cond_itr(save);
      COND_CMP *cond_cmp;
      while ((cond_cmp=cond_itr++))
4330 4331 4332 4333 4334 4335
      {
        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
4336 4337
    }
  }
4338
  else if (and_father != cond && !cond->marker)		// In a AND group
unknown's avatar
unknown committed
4339 4340 4341 4342 4343 4344
  {
    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;
4345 4346 4347
      Item **args= func->arguments();
      bool left_const= args[0]->const_item();
      bool right_const= args[1]->const_item();
4348
      if (!(left_const && right_const) &&
4349
          args[0]->result_type() == args[1]->result_type())
unknown's avatar
unknown committed
4350 4351 4352
      {
	if (right_const)
	{
4353
          resolve_const_item(thd, &args[1], args[0]);
unknown's avatar
unknown committed
4354
	  func->update_used_tables();
4355 4356
          change_cond_ref_to_const(thd, save_list, and_father, and_father,
                                   args[0], args[1]);
unknown's avatar
unknown committed
4357 4358 4359
	}
	else if (left_const)
	{
4360
          resolve_const_item(thd, &args[0], args[1]);
unknown's avatar
unknown committed
4361
	  func->update_used_tables();
4362 4363
          change_cond_ref_to_const(thd, save_list, and_father, and_father,
                                   args[1], args[0]);
unknown's avatar
unknown committed
4364 4365 4366 4367 4368 4369 4370 4371
	}
      }
    }
  }
}


static COND *
4372
optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value)
unknown's avatar
unknown committed
4373
{
4374
  SELECT_LEX *select= thd->lex->current_select;
4375
  DBUG_ENTER("optimize_cond");
4376 4377 4378 4379
  if (conds)
  {
    DBUG_EXECUTE("where", print_where(conds, "original"););
    /* change field = field to field = const for each found field = const */
4380
    propagate_cond_constants(thd, (I_List<COND_CMP> *) 0, conds, conds);
4381 4382 4383 4384 4385 4386 4387 4388 4389
    /*
      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"););
  }
  else
unknown's avatar
unknown committed
4390 4391
  {
    *cond_value= Item::COND_TRUE;
4392
    select->prep_where= 0;
unknown's avatar
unknown committed
4393
  }
4394
  DBUG_RETURN(conds);
unknown's avatar
unknown committed
4395 4396 4397 4398
}


/*
4399 4400 4401 4402 4403
  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
4404 4405 4406
*/

static COND *
4407
remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
unknown's avatar
unknown committed
4408 4409 4410 4411 4412 4413 4414
{
  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;
4415
    bool should_fix_fields=0;
unknown's avatar
unknown committed
4416 4417 4418 4419 4420

    *cond_value=Item::COND_UNDEF;
    Item *item;
    while ((item=li++))
    {
4421
      Item *new_item=remove_eq_conds(thd, item, &tmp_cond_value);
unknown's avatar
unknown committed
4422 4423 4424 4425 4426
      if (!new_item)
	li.remove();
      else if (item != new_item)
      {
	VOID(li.replace(new_item));
4427
	should_fix_fields=1;
unknown's avatar
unknown committed
4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453
      }
      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 */
      }
    }
4454
    if (should_fix_fields)
4455
      cond->update_used_tables();
4456

unknown's avatar
unknown committed
4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470
    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)
  {
    /*
4471 4472 4473 4474 4475 4476 4477
      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
4478 4479 4480 4481 4482 4483 4484 4485
    */

    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 &&
4486 4487
	  (thd->options & OPTION_AUTO_IS_NULL) &&
	  thd->insert_id())
unknown's avatar
unknown committed
4488
      {
4489
#ifndef EMBEDDED_LIBRARY
unknown's avatar
unknown committed
4490
	query_cache_abort(&thd->net);
4491
#endif
unknown's avatar
unknown committed
4492 4493 4494
	COND *new_cond;
	if ((new_cond= new Item_func_eq(args[0],
					new Item_int("last_insert_id()",
4495
						     thd->insert_id(),
unknown's avatar
unknown committed
4496 4497 4498
						     21))))
	{
	  cond=new_cond;
unknown's avatar
unknown committed
4499
	  cond->fix_fields(thd, 0, &cond);
unknown's avatar
unknown committed
4500
	}
4501
	thd->insert_id(0);		// Clear for next request
unknown's avatar
unknown committed
4502 4503 4504 4505
      }
      /* fix to replace 'NULL' dates with '0' (shreeve@uci.edu) */
      else if (((field->type() == FIELD_TYPE_DATE) ||
		(field->type() == FIELD_TYPE_DATETIME)) &&
4506 4507
		(field->flags & NOT_NULL_FLAG) &&
	       !field->table->maybe_null)
unknown's avatar
unknown committed
4508 4509 4510 4511 4512
      {
	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
4513
	  cond->fix_fields(thd, 0, &cond);
unknown's avatar
unknown committed
4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526
	}
      }
    }
  }
  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];
4527
    if (left_item->eq(right_item,1))
unknown's avatar
unknown committed
4528 4529 4530 4531 4532 4533 4534
    {
      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;
4535
  return cond;					// Point at next and level
unknown's avatar
unknown committed
4536 4537 4538
}

/*
4539
  Return 1 if the item is a const value in all the WHERE clause
unknown's avatar
unknown committed
4540 4541 4542 4543 4544 4545 4546 4547 4548
*/

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
4549
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571
    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];
4572
    if (left_item->eq(comp_item,1))
unknown's avatar
unknown committed
4573 4574 4575 4576
    {
      if (right_item->const_item())
      {
	if (*const_item)
4577
	  return right_item->eq(*const_item, 1);
unknown's avatar
unknown committed
4578 4579 4580 4581
	*const_item=right_item;
	return 1;
      }
    }
4582
    else if (right_item->eq(comp_item,1))
unknown's avatar
unknown committed
4583 4584 4585 4586
    {
      if (left_item->const_item())
      {
	if (*const_item)
4587
	  return left_item->eq(*const_item, 1);
unknown's avatar
unknown committed
4588 4589 4590 4591 4592 4593 4594 4595 4596 4597
	*const_item=left_item;
	return 1;
      }
    }
  }
  return 0;
}


/****************************************************************************
unknown's avatar
unknown committed
4598
  Create internal temporary table
unknown's avatar
unknown committed
4599 4600
****************************************************************************/

4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616
/*
  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
4617 4618
    convert_blob_length If >0 create a varstring(convert_blob_length) field 
                        instead of blob.
4619 4620 4621 4622 4623

  RETURN
    0			on error
    new_created field
*/
4624 4625 4626 4627 4628

static Field* create_tmp_field_from_field(THD *thd, Field* org_field,
                                          Item *item, TABLE *table,
                                          bool modify_item,
                                          uint convert_blob_length)
4629 4630 4631
{
  Field *new_field;

4632 4633 4634 4635 4636
  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
4637
    new_field= org_field->new_field(thd->mem_root, table);
4638
  if (new_field)
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
  {
    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
4669 4670
    convert_blob_length If >0 create a varstring(convert_blob_length) field 
                        instead of blob.
4671 4672 4673 4674 4675

  RETURN
    0			on error
    new_created field
*/
4676 4677 4678
static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
                                         Item ***copy_func, bool modify_item,
                                         uint convert_blob_length)
4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694
{
  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)
4695 4696 4697 4698 4699 4700 4701 4702 4703
    {
      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);
    }
4704
    else
4705 4706
      new_field= new Field_string(item->max_length, maybe_null, item->name, 
                                  table, item->collation.collation);
4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721
    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
4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732
/*
  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
4733
    from_field          if field will be created using other field as example,
unknown's avatar
unknown committed
4734
                        pointer example field will be written here
unknown's avatar
unknown committed
4735 4736 4737 4738 4739 4740 4741 4742
    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
4743 4744
    convert_blob_length If >0 create a varstring(convert_blob_length) field 
                        instead of blob.
unknown's avatar
unknown committed
4745

unknown's avatar
unknown committed
4746 4747 4748 4749 4750
  RETURN
    0			on error
    new_created field
*/

unknown's avatar
unknown committed
4751
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
4752 4753
                        Item ***copy_func, Field **from_field,
                        bool group, bool modify_item, uint convert_blob_length)
unknown's avatar
unknown committed
4754 4755 4756 4757 4758 4759 4760 4761 4762 4763
{
  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
4764
				0, item->name,table,&my_charset_bin);
unknown's avatar
unknown committed
4765 4766 4767
      else
	return new Field_double(item_sum->max_length,maybe_null,
				item->name, table, item_sum->decimals);
unknown's avatar
unknown committed
4768
    case Item_sum::VARIANCE_FUNC:		/* Place for sum & count */
unknown's avatar
unknown committed
4769
    case Item_sum::STD_FUNC:
unknown's avatar
unknown committed
4770 4771
      if (group)
	return	new Field_string(sizeof(double)*2+sizeof(longlong),
unknown's avatar
unknown committed
4772
				 0, item->name,table,&my_charset_bin);
unknown's avatar
unknown committed
4773 4774
      else
	return new Field_double(item_sum->max_length, maybe_null,
unknown's avatar
unknown committed
4775
				item->name,table,item_sum->decimals);
unknown's avatar
unknown committed
4776 4777 4778 4779 4780 4781 4782 4783 4784
    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,
4785
				  item->name,table,item->unsigned_flag);
unknown's avatar
unknown committed
4786 4787
      case STRING_RESULT:
	if (item_sum->max_length > 255)
4788 4789 4790 4791 4792 4793 4794 4795 4796
        {
          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
4797
	return	new Field_string(item_sum->max_length,maybe_null,
4798
				 item->name,table,item->collation.collation);
4799
      case ROW_RESULT:
unknown's avatar
unknown committed
4800
      default:
unknown's avatar
unknown committed
4801 4802
	// This case should never be choosen
	DBUG_ASSERT(0);
unknown's avatar
unknown committed
4803
	thd->fatal_error();
unknown's avatar
unknown committed
4804
	return 0;
unknown's avatar
unknown committed
4805 4806
      }
    }
unknown's avatar
unknown committed
4807
    /* We never come here */
unknown's avatar
unknown committed
4808 4809
  }
  case Item::FIELD_ITEM:
4810
  case Item::DEFAULT_VALUE_ITEM:
unknown's avatar
unknown committed
4811 4812
  {
    Item_field *field= (Item_field*) item;
4813 4814
    return create_tmp_field_from_field(thd, (*from_field= field->field), item,
                                       table, modify_item, convert_blob_length);
unknown's avatar
unknown committed
4815
  }
unknown's avatar
unknown committed
4816 4817 4818 4819
  case Item::FUNC_ITEM:
  case Item::COND_ITEM:
  case Item::FIELD_AVG_ITEM:
  case Item::FIELD_STD_ITEM:
4820
  case Item::SUBSELECT_ITEM:
unknown's avatar
unknown committed
4821
    /* The following can only happen with 'CREATE TABLE ... SELECT' */
unknown's avatar
unknown committed
4822
  case Item::PROC_ITEM:
unknown's avatar
unknown committed
4823 4824 4825 4826
  case Item::INT_ITEM:
  case Item::REAL_ITEM:
  case Item::STRING_ITEM:
  case Item::REF_ITEM:
4827
  case Item::NULL_ITEM:
4828
  case Item::VARBIN_ITEM:
4829 4830
    return create_tmp_field_from_item(thd, item, table, copy_func, modify_item,
                                      convert_blob_length);
4831
  case Item::TYPE_HOLDER:
unknown's avatar
unknown committed
4832
  {
4833 4834
    Field *example= ((Item_type_holder *)item)->example();
    if (example)
4835 4836 4837 4838
      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
4839 4840 4841 4842 4843 4844 4845
  }
  default:					// Dosen't have to be stored
    return 0;
  }
}


unknown's avatar
unknown committed
4846 4847 4848 4849 4850 4851 4852
/*
  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
4853 4854 4855
TABLE *
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
		 ORDER *group, bool distinct, bool save_sum_fields,
4856 4857
		 ulong select_options, ha_rows rows_limit,
		 char *table_alias)
unknown's avatar
unknown committed
4858 4859 4860
{
  TABLE *table;
  uint	i,field_count,reclength,null_count,null_pack_length,
unknown's avatar
unknown committed
4861
        hidden_null_count, hidden_null_pack_length, hidden_field_count,
unknown's avatar
unknown committed
4862 4863
	blob_count,group_null_items;
  bool	using_unique_constraint=0;
unknown's avatar
unknown committed
4864
  bool  not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS);
unknown's avatar
unknown committed
4865 4866 4867
  char	*tmpname,path[FN_REFLEN];
  byte	*pos,*group_buff;
  uchar *null_flags;
4868
  Field **reg_field, **from_field, **blob_field;
unknown's avatar
unknown committed
4869 4870 4871
  Copy_field *copy=0;
  KEY *keyinfo;
  KEY_PART_INFO *key_part_info;
unknown's avatar
unknown committed
4872
  Item **copy_func;
unknown's avatar
unknown committed
4873
  MI_COLUMNDEF *recinfo;
4874
  uint temp_pool_slot=MY_BIT_NONE;
4875

unknown's avatar
unknown committed
4876
  DBUG_ENTER("create_tmp_table");
unknown's avatar
unknown committed
4877
  DBUG_PRINT("enter",("distinct: %d  save_sum_fields: %d  rows_limit: %lu  group: %d",
unknown's avatar
unknown committed
4878
		      (int) distinct, (int) save_sum_fields,
unknown's avatar
unknown committed
4879
		      (ulong) rows_limit,test(group)));
unknown's avatar
unknown committed
4880

4881
  statistic_increment(created_tmp_tables, &LOCK_status);
4882

4883
  if (use_temp_pool)
unknown's avatar
unknown committed
4884
    temp_pool_slot = bitmap_set_next(&temp_pool);
4885 4886

  if (temp_pool_slot != MY_BIT_NONE) // we got a slot
4887
    sprintf(path, "%s%s_%lx_%i", mysql_tmpdir, tmp_file_prefix,
4888 4889
	    current_pid, temp_pool_slot);
  else // if we run out of slots or we are not using tempool
4890 4891
    sprintf(path,"%s%s%lx_%lx_%x",mysql_tmpdir,tmp_file_prefix,current_pid,
            thd->thread_id, thd->tmp_table++);
unknown's avatar
unknown committed
4892

4893 4894
  if (lower_case_table_names)
    my_casedn_str(files_charset_info, path);
4895

unknown's avatar
unknown committed
4896 4897 4898 4899 4900
  if (group)
  {
    if (!param->quick_group)
      group=0;					// Can't use group key
    else for (ORDER *tmp=group ; tmp ; tmp=tmp->next)
4901
    {
unknown's avatar
unknown committed
4902
      (*tmp->item)->marker=4;			// Store null in key
4903 4904 4905
      if ((*tmp->item)->max_length >= MAX_CHAR_WIDTH)
	using_unique_constraint=1;
    }
unknown's avatar
unknown committed
4906 4907
    if (param->group_length >= MAX_BLOB_WIDTH)
      using_unique_constraint=1;
unknown's avatar
unknown committed
4908 4909
    if (group)
      distinct=0;				// Can't use distinct
unknown's avatar
unknown committed
4910 4911 4912
  }

  field_count=param->field_count+param->func_count+param->sum_func_count;
unknown's avatar
unknown committed
4913
  hidden_field_count=param->hidden_field_count;
unknown's avatar
unknown committed
4914 4915
  if (!my_multi_malloc(MYF(MY_WME),
		       &table,sizeof(*table),
4916 4917 4918
		       &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
4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929
		       &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
4930
    bitmap_clear_bit(&temp_pool, temp_pool_slot);
4931
    DBUG_RETURN(NULL);				/* purecov: inspected */
unknown's avatar
unknown committed
4932 4933 4934
  }
  if (!(param->copy_field=copy=new Copy_field[field_count]))
  {
unknown's avatar
unknown committed
4935
    bitmap_clear_bit(&temp_pool, temp_pool_slot);
4936 4937
    my_free((gptr) table,MYF(0));		/* purecov: inspected */
    DBUG_RETURN(NULL);				/* purecov: inspected */
unknown's avatar
unknown committed
4938
  }
unknown's avatar
unknown committed
4939
  param->items_to_copy= copy_func;
unknown's avatar
unknown committed
4940 4941 4942 4943 4944 4945 4946
  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;
4947
  table->blob_field= (Field_blob**) blob_field;
unknown's avatar
unknown committed
4948
  table->real_name=table->path=tmpname;
4949
  table->table_name= table_alias;
unknown's avatar
unknown committed
4950 4951 4952 4953
  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
4954
  table->tmp_table= TMP_TABLE;
unknown's avatar
unknown committed
4955
  table->db_low_byte_first=1;			// True for HEAP and MyISAM
4956
  table->temp_pool_slot = temp_pool_slot;
4957
  table->copy_blobs= 1;
4958
  table->in_use= thd;
4959 4960 4961 4962 4963 4964
  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
4965

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

unknown's avatar
unknown committed
4968 4969
  reclength=blob_count=null_count=hidden_null_count=group_null_items=0;
  param->using_indirect_summary_function=0;
unknown's avatar
unknown committed
4970

unknown's avatar
unknown committed
4971
  List_iterator_fast<Item> li(fields);
unknown's avatar
unknown committed
4972 4973
  Item *item;
  Field **tmp_from_field=from_field;
4974
  while ((item=li++))
unknown's avatar
unknown committed
4975 4976
  {
    Item::Type type=item->type();
unknown's avatar
unknown committed
4977
    if (not_all_columns)
unknown's avatar
unknown committed
4978
    {
unknown's avatar
unknown committed
4979 4980 4981 4982 4983 4984 4985 4986 4987 4988
      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;
      }
4989
      if (item->const_item() && (int) hidden_field_count <= 0)
4990
        continue; // We don't have to store this
unknown's avatar
unknown committed
4991
    }
unknown's avatar
unknown committed
4992 4993 4994 4995 4996
    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++)
      {
4997 4998
	Item **argp= ((Item_sum*) item)->args + i;
	Item *arg= *argp;
unknown's avatar
unknown committed
4999 5000 5001
	if (!arg->const_item())
	{
	  Field *new_field=
5002 5003 5004
            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
5005 5006 5007 5008 5009 5010
	  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)
5011 5012
	  {
	    *blob_field++= new_field;
unknown's avatar
unknown committed
5013
	    blob_count++;
5014
	  }
5015
          thd->change_item_tree(argp, new Item_field(new_field));
unknown's avatar
unknown committed
5016 5017 5018 5019 5020 5021 5022
	  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
            */
5023
            (*argp)->maybe_null=1;
unknown's avatar
unknown committed
5024
          }
unknown's avatar
unknown committed
5025 5026 5027 5028 5029
	}
      }
    }
    else
    {
unknown's avatar
unknown committed
5030 5031 5032 5033 5034 5035 5036 5037 5038 5039
      /*
	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.
      */
5040 5041 5042 5043
      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
5044 5045
      if (!new_field)
      {
5046
	if (thd->is_fatal_error)
unknown's avatar
unknown committed
5047 5048 5049 5050 5051 5052 5053 5054 5055 5056
	  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)
5057 5058
      {
	*blob_field++= new_field;
unknown's avatar
unknown committed
5059
	blob_count++;
5060
      }
unknown's avatar
unknown committed
5061 5062 5063 5064 5065 5066 5067
      if (item->marker == 4 && item->maybe_null)
      {
	group_null_items++;
	new_field->flags|= GROUP_FLAG;
      }
      *(reg_field++) =new_field;
    }
unknown's avatar
unknown committed
5068 5069
    if (!--hidden_field_count)
      hidden_null_count=null_count;
unknown's avatar
unknown committed
5070
  }
5071
  DBUG_ASSERT(field_count >= (uint) (reg_field - table->field));
unknown's avatar
unknown committed
5072
  field_count= (uint) (reg_field - table->field);
5073
  *blob_field= 0;				// End marker
unknown's avatar
unknown committed
5074 5075

  /* If result table is small; use a heap */
5076
  if (blob_count || using_unique_constraint ||
unknown's avatar
unknown committed
5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095
      (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
5096 5097
  {
    /* We need to ensure that first byte is not 0 for the delete link */
5098
    if (param->hidden_field_count)
unknown's avatar
unknown committed
5099 5100 5101 5102 5103 5104 5105
      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
5106 5107 5108 5109 5110 5111 5112 5113
  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
5114
    if (!(table->record[0]= (byte *) my_malloc(alloc_length*3, MYF(MY_WME))))
unknown's avatar
unknown committed
5115
      goto err;
unknown's avatar
unknown committed
5116
    table->record[1]= table->record[0]+alloc_length;
unknown's avatar
unknown committed
5117
    table->default_values= table->record[1]+alloc_length;
unknown's avatar
unknown committed
5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130
  }
  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
5131 5132 5133 5134

    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
5135 5136
  }
  null_count= (blob_count == 0) ? 1 : 0;
unknown's avatar
unknown committed
5137
  hidden_field_count=param->hidden_field_count;
unknown's avatar
unknown committed
5138 5139 5140 5141 5142 5143 5144 5145 5146 5147
  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)
      {
5148 5149 5150 5151
	/*
	  We have to reserve one byte here for NULL bits,
	  as this is updated by 'end_update()'
	*/
unknown's avatar
unknown committed
5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185
	*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
5186
      recinfo->type=FIELD_SKIP_ENDSPACE;
unknown's avatar
unknown committed
5187 5188
    else
      recinfo->type=FIELD_NORMAL;
unknown's avatar
unknown committed
5189 5190
    if (!--hidden_field_count)
      null_count=(null_count+7) & ~7;		// move to next byte
5191 5192 5193

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

unknown's avatar
unknown committed
5196
  param->copy_field_end=copy;
unknown's avatar
unknown committed
5197
  param->recinfo=recinfo;
5198
  store_record(table,default_values);		// Make empty default record
unknown's avatar
unknown committed
5199

5200
  if (thd->variables.tmp_table_size == ~(ulong) 0)		// No limit
5201 5202 5203
    table->max_rows= ~(ha_rows) 0;
  else
    table->max_rows=(((table->db_type == DB_TYPE_HEAP) ?
5204 5205 5206
		      min(thd->variables.tmp_table_size,
			  thd->variables.max_heap_table_size) :
		      thd->variables.tmp_table_size)/ table->reclength);
unknown's avatar
unknown committed
5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222
  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;
5223
    keyinfo->algorithm= HA_KEY_ALG_UNDEF;
unknown's avatar
unknown committed
5224 5225
    for (; group ; group=group->next,key_part_info++)
    {
5226
      Field *field=(*group->item)->get_tmp_table_field();
unknown's avatar
unknown committed
5227
      bool maybe_null=(*group->item)->maybe_null;
5228
      key_part_info->null_bit=0;
unknown's avatar
unknown committed
5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239
      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
5240
	if (!(group->field=field->new_field(thd->mem_root,table)))
unknown's avatar
unknown committed
5241 5242 5243 5244
	  goto err; /* purecov: inspected */
	if (maybe_null)
	{
	  /*
5245 5246 5247 5248
	    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
5249
	  */
5250 5251 5252 5253 5254
	  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);
5255
	  group_buff++;
unknown's avatar
unknown committed
5256 5257 5258 5259 5260 5261 5262 5263 5264
	}
	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
5265
  if (distinct)
unknown's avatar
unknown committed
5266
  {
unknown's avatar
unknown committed
5267 5268 5269 5270 5271 5272
    /*
      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.
    */
5273 5274
    DBUG_PRINT("info",("hidden_field_count: %d", param->hidden_field_count));

unknown's avatar
unknown committed
5275
    null_pack_length-=hidden_null_pack_length;
unknown's avatar
unknown committed
5276
    keyinfo->key_parts= ((field_count-param->hidden_field_count)+
5277
			 test(null_pack_length));
unknown's avatar
unknown committed
5278 5279
    set_if_smaller(table->max_rows, rows_limit);
    param->end_write_records= rows_limit;
unknown's avatar
unknown committed
5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291
    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;
5292
    keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL;
unknown's avatar
unknown committed
5293 5294
    keyinfo->key_length=(uint16) reclength;
    keyinfo->name=(char*) "tmp";
5295
    keyinfo->algorithm= HA_KEY_ALG_UNDEF;
5296
    keyinfo->rec_per_key=0;
unknown's avatar
unknown committed
5297
    if (null_pack_length)
unknown's avatar
unknown committed
5298
    {
5299
      key_part_info->null_bit=0;
unknown's avatar
unknown committed
5300 5301
      key_part_info->offset=hidden_null_pack_length;
      key_part_info->length=null_pack_length;
unknown's avatar
unknown committed
5302 5303 5304 5305 5306
      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
5307
					    NullS, table, &my_charset_bin);
unknown's avatar
unknown committed
5308 5309 5310 5311
      key_part_info->key_type=FIELDFLAG_BINARY;
      key_part_info->type=    HA_KEYTYPE_BINARY;
      key_part_info++;
    }
5312
    /* Create a distinct key over the columns we are going to return */
unknown's avatar
unknown committed
5313 5314
    for (i=param->hidden_field_count, reg_field=table->field + i ;
	 i < field_count;
unknown's avatar
unknown committed
5315 5316
	 i++, reg_field++, key_part_info++)
    {
5317
      key_part_info->null_bit=0;
unknown's avatar
unknown committed
5318 5319 5320 5321 5322 5323 5324 5325 5326 5327
      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;
    }
  }
5328
  if (thd->is_fatal_error)				// If end of memory
unknown's avatar
unknown committed
5329 5330 5331 5332 5333 5334 5335
    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;
  }
5336 5337
  /* Set table_name for easier debugging */
  table->table_name= base_name(tmpname);
unknown's avatar
unknown committed
5338 5339 5340 5341
  if (!open_tmp_table(table))
    DBUG_RETURN(table);

 err:
5342 5343 5344 5345 5346
  /*
    Hack to ensure that free_blobs() doesn't fail if blob_field is not yet
    complete
  */
  *table->blob_field= 0;
5347
  free_tmp_table(thd,table);                    /* purecov: inspected */
unknown's avatar
unknown committed
5348
  bitmap_clear_bit(&temp_pool, temp_pool_slot);
unknown's avatar
unknown committed
5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367
  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,
5368
				    ulong options)
unknown's avatar
unknown committed
5369 5370 5371 5372 5373 5374 5375 5376 5377 5378
{
  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
5379
    HA_KEYSEG *seg= (HA_KEYSEG*) sql_calloc(sizeof(*seg) *
unknown's avatar
unknown committed
5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414
					    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;
5415
      seg->flag=     0;
unknown's avatar
unknown committed
5416
      seg->language= field->charset()->number;
5417 5418
      seg->length=   keyinfo->key_part[i].length;
      seg->start=    keyinfo->key_part[i].offset;
unknown's avatar
unknown committed
5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438
      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;
      }
5439
      if (!(field->flags & NOT_NULL_FLAG))
unknown's avatar
unknown committed
5440 5441 5442
      {
	seg->null_bit= field->null_bit;
	seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]);
5443 5444 5445 5446 5447 5448 5449
	/*
	  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
5450 5451 5452 5453 5454
      }
    }
  }
  MI_CREATE_INFO create_info;
  bzero((char*) &create_info,sizeof(create_info));
unknown's avatar
unknown committed
5455

5456 5457
  if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
      OPTION_BIG_TABLES)
unknown's avatar
unknown committed
5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470
    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;
  }
unknown's avatar
unknown committed
5471
  statistic_increment(created_tmp_disk_tables, &LOCK_status);
unknown's avatar
unknown committed
5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487
  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";
5488
  free_blobs(entry);
5489
  if (entry->file)
unknown's avatar
unknown committed
5490
  {
5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501
    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
5502 5503
    delete entry->file;
  }
5504

unknown's avatar
unknown committed
5505 5506
  /* free blobs */
  for (Field **ptr=entry->field ; *ptr ; ptr++)
5507
    (*ptr)->free();
unknown's avatar
unknown committed
5508 5509
  my_free((gptr) entry->record[0],MYF(0));
  free_io_cache(entry);
5510

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

unknown's avatar
unknown committed
5513 5514 5515 5516 5517 5518 5519 5520 5521 5522
  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
5523 5524
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
5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544
{
  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,
5545
			      thd->lex->select_lex.options | thd->options))
unknown's avatar
unknown committed
5546 5547 5548
    goto err2;
  if (open_tmp_table(&new_table))
    goto err1;
5549 5550
  if (table->file->indexes_are_disabled())
    new_table.file->disable_indexes(HA_KEY_SWITCH_ALL);
unknown's avatar
unknown committed
5551
  table->file->ha_index_or_rnd_end();
5552
  table->file->ha_rnd_init(1);
5553 5554
  if (table->no_rows)
  {
5555 5556
    new_table.file->extra(HA_EXTRA_NO_ROWS);
    new_table.no_rows=1;
5557 5558
  }

5559 5560 5561 5562 5563 5564 5565 5566
#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
unknown's avatar
unknown committed
5567
  /* HA_EXTRA_WRITE_CACHE can stay until close, no need to disable it */
5568 5569 5570
  new_table.file->extra(HA_EXTRA_WRITE_CACHE);
#endif

unknown's avatar
unknown committed
5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585
  /* 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
5586
  (void) table->file->ha_rnd_end();
unknown's avatar
unknown committed
5587 5588 5589 5590 5591 5592
  (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);
5593 5594
  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
5595 5596 5597 5598 5599
  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
5600
  (void) table->file->ha_rnd_end();
unknown's avatar
unknown committed
5601 5602 5603 5604 5605 5606 5607 5608 5609 5610
  (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);
}


5611 5612 5613 5614 5615 5616
/****************************************************************************
  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
5617 5618 5619 5620

static int
do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
{
5621
  int error= 0;
unknown's avatar
unknown committed
5622 5623 5624 5625 5626 5627
  JOIN_TAB *join_tab;
  int (*end_select)(JOIN *, struct st_join_table *,bool);
  DBUG_ENTER("do_select");

  join->procedure=procedure;
  /*
5628
    Tell the client how many fields there are in a row
unknown's avatar
unknown committed
5629 5630 5631 5632 5633 5634 5635 5636
  */
  if (!table)
    join->result->send_fields(*fields,1);
  else
  {
    VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
    empty_record(table);
  }
unknown's avatar
unknown committed
5637
  join->tmp_table= table;			/* Save for easy recursion */
unknown's avatar
unknown committed
5638 5639 5640 5641 5642 5643 5644 5645 5646
  join->fields= fields;

  /* Set up select_end */
  if (table)
  {
    if (table->group && join->tmp_table_param.sum_func_count)
    {
      if (table->keys)
      {
5647
	DBUG_PRINT("info",("Using end_update"));
unknown's avatar
unknown committed
5648
	end_select=end_update;
unknown's avatar
unknown committed
5649 5650
        if (!table->file->inited)
          table->file->ha_index_init(0);
unknown's avatar
unknown committed
5651 5652
      }
      else
5653 5654
      {
	DBUG_PRINT("info",("Using end_unique_update"));
unknown's avatar
unknown committed
5655
	end_select=end_unique_update;
5656
      }
unknown's avatar
unknown committed
5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682
    }
    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
  {
    if (join->sort_and_group || (join->procedure &&
				 join->procedure->flags & PROC_GROUP))
      end_select=end_send_group;
    else
      end_select=end_send;
  }
  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)
  {
5683 5684 5685 5686
    /*
      HAVING will be chcked after processing aggregate functions,
      But WHERE should checkd here (we alredy have read tables)
    */
unknown's avatar
unknown committed
5687
    if (!join->conds || join->conds->val_int())
unknown's avatar
unknown committed
5688
    {
5689 5690
      if (!(error=(*end_select)(join,join_tab,0)) || error == -3)
	error=(*end_select)(join,join_tab,1);
unknown's avatar
unknown committed
5691
    }
5692
    else if (join->send_row_on_empty_set())
5693
      error= join->result->send_data(*join->fields);
unknown's avatar
unknown committed
5694 5695 5696
  }
  else
  {
unknown's avatar
unknown committed
5697
    error= sub_select(join,join_tab,0);
unknown's avatar
unknown committed
5698
    if (error >= 0)
unknown's avatar
unknown committed
5699
      error= sub_select(join,join_tab,1);
unknown's avatar
unknown committed
5700
    if (error == -3)
unknown's avatar
unknown committed
5701
      error= 0;					/* select_limit used */
unknown's avatar
unknown committed
5702
  }
5703

unknown's avatar
unknown committed
5704
  if (error >= 0)
unknown's avatar
unknown committed
5705
  {
5706 5707
    error=0;
    if (!table)					// If sending data to client
5708
    {
5709
      /*
5710 5711
	The following will unlock all cursors if the command wasn't an
	update command
5712
      */
5713
      join->join_free(0);				// Unlock all cursors
5714
      if (join->result->send_eof())
5715
	error= 1;				// Don't send error
5716
    }
unknown's avatar
unknown committed
5717 5718 5719 5720
    DBUG_PRINT("info",("%ld records output",join->send_records));
  }
  if (table)
  {
5721
    int tmp;
unknown's avatar
unknown committed
5722 5723
    if ((tmp=table->file->extra(HA_EXTRA_NO_CACHE)))
    {
5724 5725
      DBUG_PRINT("error",("extra(HA_EXTRA_NO_CACHE) failed"));
      my_errno= tmp;
unknown's avatar
unknown committed
5726 5727
      error= -1;
    }
unknown's avatar
unknown committed
5728
    if ((tmp=table->file->ha_index_or_rnd_end()))
unknown's avatar
unknown committed
5729
    {
unknown's avatar
unknown committed
5730
      DBUG_PRINT("error",("ha_index_or_rnd_end() failed"));
5731
      my_errno= tmp;
unknown's avatar
unknown committed
5732 5733
      error= -1;
    }
5734
    if (error == -1)
unknown's avatar
unknown committed
5735 5736
      table->file->print_error(my_errno,MYF(0));
  }
5737 5738 5739 5740 5741 5742
#ifndef DBUG_OFF
  if (error)
  {
    DBUG_PRINT("error",("Error: do_select() failed"));
  }
#endif
unknown's avatar
unknown committed
5743
  DBUG_RETURN(join->thd->net.report_error ? -1 : error);
unknown's avatar
unknown committed
5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757
}


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);
  }
5758 5759 5760 5761 5762
  if (join->thd->killed)		// If aborted by user
  {
    my_error(ER_SERVER_SHUTDOWN,MYF(0)); /* purecov: inspected */
    return -2;				 /* purecov: inspected */
  }
unknown's avatar
unknown committed
5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786
  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 */
}


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

  /* Cache variables for faster loop */
  int error;
  bool found=0;
  COND *on_expr=join_tab->on_expr, *select_cond=join_tab->select_cond;
5787
  my_bool *report_error= &(join->thd->net.report_error);
unknown's avatar
unknown committed
5788 5789 5790

  if (!(error=(*join_tab->read_first_record)(join_tab)))
  {
unknown's avatar
unknown committed
5791 5792 5793
    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
5794 5795
    READ_RECORD *info= &join_tab->read_record;

5796
    join->thd->row_count= 0;
unknown's avatar
unknown committed
5797 5798 5799 5800 5801 5802 5803
    do
    {
      if (join->thd->killed)			// Aborted by user
      {
	my_error(ER_SERVER_SHUTDOWN,MYF(0));	/* purecov: inspected */
	return -2;				/* purecov: inspected */
      }
5804
      join->examined_rows++;
5805
      join->thd->row_count++;
unknown's avatar
unknown committed
5806 5807 5808 5809 5810 5811 5812
      if (!on_expr || on_expr->val_int())
      {
	found=1;
	if (not_exists_optimize)
	  break;			// Searching after not null columns
	if (!select_cond || select_cond->val_int())
	{
5813
	  if ((error=(*join_tab->next_select)(join,join_tab+1,0)) < 0)
unknown's avatar
unknown committed
5814
	    return error;
unknown's avatar
unknown committed
5815 5816 5817 5818 5819
	  /*
	    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
5820 5821
	  if (not_used_in_distinct && found_records != join->found_records)
	    return 0;
unknown's avatar
unknown committed
5822
	}
unknown's avatar
unknown committed
5823
	else
unknown's avatar
unknown committed
5824 5825 5826 5827 5828 5829 5830
        {
          /* 
            This row failed selection, release lock on it.
            XXX: There is no table handler in MySQL which makes use of this
            call. It's kept from Gemini times. A lot of new code was added
            recently (i. e. subselects) without having it in mind.
          */
unknown's avatar
unknown committed
5831
	  info->file->unlock_row();
unknown's avatar
unknown committed
5832
        }
unknown's avatar
unknown committed
5833
      }
5834
    } while (!(error=info->read_record(info)) && !(*report_error));
unknown's avatar
unknown committed
5835
  }
5836
  if (error > 0 || (*report_error))				// Fatal error
unknown's avatar
unknown committed
5837 5838 5839 5840
    return -1;

  if (!found && on_expr)
  {						// OUTER JOIN
unknown's avatar
unknown committed
5841
    restore_record(join_tab->table,default_values);		// Make empty record
unknown's avatar
unknown committed
5842 5843 5844
    mark_as_null_row(join_tab->table);		// For group by without error
    if (!select_cond || select_cond->val_int())
    {
5845
      if ((error=(*join_tab->next_select)(join,join_tab+1,0)) < 0)
unknown's avatar
unknown committed
5846 5847 5848 5849 5850 5851 5852 5853
	return error;				/* purecov: inspected */
    }
  }
  return 0;
}


static int
5854
flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last)
unknown's avatar
unknown committed
5855 5856 5857 5858 5859 5860
{
  int error;
  READ_RECORD *info;

  if (!join_tab->cache.records)
    return 0;				/* Nothing to do */
5861
  if (skip_last)
unknown's avatar
unknown committed
5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873
    (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)))
  {
5874
    reset_cache_write(&join_tab->cache);
unknown's avatar
unknown committed
5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893
    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)
    {
      my_error(ER_SERVER_SHUTDOWN,MYF(0)); /* purecov: inspected */
      return -2;				// Aborted by user /* purecov: inspected */
    }
    SQL_SELECT *select=join_tab->select;
    if (!error && (!join_tab->cache.select ||
5894
		   !join_tab->cache.select->skip_record()))
unknown's avatar
unknown committed
5895 5896
    {
      uint i;
5897
      reset_cache_read(&join_tab->cache);
5898
      for (i=(join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;)
unknown's avatar
unknown committed
5899 5900
      {
	read_cached_record(join_tab);
5901
	if (!select || !select->skip_record())
unknown's avatar
unknown committed
5902
	  if ((error=(join_tab->next_select)(join,join_tab+1,0)) < 0)
5903 5904
          {
            reset_cache_write(&join_tab->cache);
unknown's avatar
unknown committed
5905
	    return error; /* purecov: inspected */
5906
          }
unknown's avatar
unknown committed
5907 5908 5909 5910
      }
    }
  } while (!(error=info->read_record(info)));

5911
  if (skip_last)
unknown's avatar
unknown committed
5912
    read_cached_record(join_tab);		// Restore current record
5913
  reset_cache_write(&join_tab->cache);
unknown's avatar
unknown committed
5914 5915 5916 5917 5918 5919 5920 5921 5922
  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;
}


/*****************************************************************************
5923 5924
  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
5925
*****************************************************************************/
5926 5927 5928

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

5929
int report_error(TABLE *table, int error)
5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947
{
  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;
}


5948
int safe_index_read(JOIN_TAB *tab)
5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959
{
  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
5960
static int
5961
join_read_const_table(JOIN_TAB *tab, POSITION *pos)
unknown's avatar
unknown committed
5962 5963
{
  int error;
5964 5965 5966 5967 5968 5969 5970
  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
5971
  {
5972 5973 5974 5975 5976 5977 5978
    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
5979
    }
5980 5981 5982
  }
  else
  {
5983
    if (!table->key_read && table->used_keys.is_set(tab->ref.key) &&
5984 5985
	!table->no_keyread &&
        (int) table->reginfo.lock_type <= (int) TL_READ_HIGH_PRIORITY)
5986 5987 5988
    {
      table->key_read=1;
      table->file->extra(HA_EXTRA_KEYREAD);
unknown's avatar
unknown committed
5989
      tab->index= tab->ref.key;
5990
    }
5991
    if ((error=join_read_const(tab)))
unknown's avatar
unknown committed
5992
    {
5993 5994 5995 5996 5997
      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
5998
    }
unknown's avatar
unknown committed
5999 6000 6001 6002 6003
    if (table->key_read)
    {
      table->key_read=0;
      table->file->extra(HA_EXTRA_NO_KEYREAD);
    }
unknown's avatar
unknown committed
6004
  }
6005 6006 6007
  if (tab->on_expr && !table->null_row)
  {
    if ((table->null_row= test(tab->on_expr->val_int() == 0)))
unknown's avatar
unknown committed
6008 6009
      mark_as_null_row(table);  
  }
6010 6011
  if (!table->null_row)
    table->maybe_null=0;
unknown's avatar
unknown committed
6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022
  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
  {
6023 6024
    if ((error=table->file->read_first_row(table->record[0],
					   table->primary_key)))
unknown's avatar
unknown committed
6025 6026
    {
      if (error != HA_ERR_END_OF_FILE)
6027
	return report_error(table, error);
unknown's avatar
unknown committed
6028
      mark_as_null_row(tab->table);
unknown's avatar
unknown committed
6029 6030 6031
      empty_record(table);			// Make empty record
      return -1;
    }
unknown's avatar
unknown committed
6032
    store_record(table,record[1]);
unknown's avatar
unknown committed
6033 6034
  }
  else if (!table->status)			// Only happens with left join
unknown's avatar
unknown committed
6035
    restore_record(table,record[1]);			// restore old record
unknown's avatar
unknown committed
6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057
  table->null_row=0;
  return table->status ? -1 : 0;
}


static int
join_read_const(JOIN_TAB *tab)
{
  int error;
  TABLE *table= tab->table;
  if (table->status & STATUS_GARBAGE)		// If first read
  {
    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)
    {
unknown's avatar
unknown committed
6058
      mark_as_null_row(tab->table);
unknown's avatar
unknown committed
6059 6060
      empty_record(table);
      if (error != HA_ERR_KEY_NOT_FOUND)
6061
	return report_error(table, error);
unknown's avatar
unknown committed
6062 6063
      return -1;
    }
unknown's avatar
unknown committed
6064
    store_record(table,record[1]);
unknown's avatar
unknown committed
6065
  }
unknown's avatar
unknown committed
6066 6067 6068
  else if (!(table->status & ~STATUS_NULL_ROW))	// Only happens with left join
  {
    table->status=0;
unknown's avatar
unknown committed
6069
    restore_record(table,record[1]);			// restore old record
unknown's avatar
unknown committed
6070
  }
unknown's avatar
unknown committed
6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081
  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
6082 6083
  if (!table->file->inited)
    table->file->ha_index_init(tab->ref.key);
unknown's avatar
unknown committed
6084
  if (cmp_buffer_with_ref(tab) ||
6085
      (table->status & (STATUS_GARBAGE | STATUS_NO_PARENT | STATUS_NULL_ROW)))
unknown's avatar
unknown committed
6086 6087 6088 6089 6090 6091 6092 6093 6094 6095
  {
    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)
6096
      return report_error(table, error);
unknown's avatar
unknown committed
6097
  }
6098
  table->null_row=0;
unknown's avatar
unknown committed
6099 6100 6101 6102 6103 6104 6105 6106 6107 6108
  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
6109 6110
  if (!table->file->inited)
    table->file->ha_index_init(tab->ref.key);
unknown's avatar
unknown committed
6111 6112 6113 6114 6115 6116 6117
  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)
6118
      return report_error(table, error);
unknown's avatar
unknown committed
6119 6120 6121 6122 6123
    return -1; /* purecov: inspected */
  }
  return 0;
}

6124

6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135
/*
  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
6136 6137
  if (!table->file->inited)
    table->file->ha_index_init(tab->ref.key);
6138 6139 6140 6141 6142 6143 6144
  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)
6145
      return report_error(table, error);
6146 6147 6148 6149 6150
    return -1; /* purecov: inspected */
  }
  return 0;
}

unknown's avatar
unknown committed
6151 6152 6153 6154 6155 6156 6157 6158 6159 6160

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


static int
6161
join_read_next_same(READ_RECORD *info)
unknown's avatar
unknown committed
6162 6163 6164 6165 6166 6167 6168 6169 6170 6171
{
  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)
6172
      return report_error(table, error);
unknown's avatar
unknown committed
6173 6174 6175 6176 6177 6178
    table->status= STATUS_GARBAGE;
    return -1;
  }
  return 0;
}

6179

6180 6181 6182 6183 6184 6185 6186 6187
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])))
6188
    return report_error(table, error);
unknown's avatar
unknown committed
6189 6190
  if (key_cmp_if_same(table, tab->ref.key_buff, tab->ref.key,
                      tab->ref.key_length))
6191 6192
  {
    table->status=STATUS_NOT_FOUND;
6193
    error= -1;
6194 6195 6196 6197
  }
  return error;
}

unknown's avatar
unknown committed
6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212

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;
6213 6214
  return tab->select->test_quick_select(tab->join->thd, tab->keys,
					(table_map) 0, HA_POS_ERROR);
unknown's avatar
unknown committed
6215 6216 6217 6218 6219 6220 6221 6222
}


static int
join_init_read_record(JOIN_TAB *tab)
{
  if (tab->select && tab->select->quick)
    tab->select->quick->reset();
6223 6224
  init_read_record(&tab->read_record, tab->join->thd, tab->table,
		   tab->select,1,1);
unknown's avatar
unknown committed
6225 6226 6227
  return (*tab->read_record.read_record)(&tab->read_record);
}

6228

unknown's avatar
unknown committed
6229
static int
6230
join_read_first(JOIN_TAB *tab)
unknown's avatar
unknown committed
6231 6232 6233
{
  int error;
  TABLE *table=tab->table;
6234
  if (!table->key_read && table->used_keys.is_set(tab->index) &&
unknown's avatar
unknown committed
6235
      !table->no_keyread)
unknown's avatar
unknown committed
6236 6237 6238 6239 6240
  {
    table->key_read=1;
    table->file->extra(HA_EXTRA_KEYREAD);
  }
  tab->table->status=0;
6241
  tab->read_record.read_record=join_read_next;
unknown's avatar
unknown committed
6242 6243 6244 6245
  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
6246 6247
  if (!table->file->inited)
    table->file->ha_index_init(tab->index);
6248
  if ((error=tab->table->file->index_first(tab->table->record[0])))
unknown's avatar
unknown committed
6249 6250
  {
    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
6251
      report_error(table, error);
unknown's avatar
unknown committed
6252 6253 6254 6255 6256
    return -1;
  }
  return 0;
}

6257

unknown's avatar
unknown committed
6258
static int
6259
join_read_next(READ_RECORD *info)
unknown's avatar
unknown committed
6260
{
6261 6262 6263
  int error;
  if ((error=info->file->index_next(info->record)))
    return report_error(info->table, error);
unknown's avatar
unknown committed
6264 6265 6266
  return 0;
}

6267

unknown's avatar
unknown committed
6268
static int
6269
join_read_last(JOIN_TAB *tab)
unknown's avatar
unknown committed
6270 6271 6272
{
  TABLE *table=tab->table;
  int error;
6273
  if (!table->key_read && table->used_keys.is_set(tab->index) &&
6274
      !table->no_keyread)
unknown's avatar
unknown committed
6275 6276 6277 6278 6279
  {
    table->key_read=1;
    table->file->extra(HA_EXTRA_KEYREAD);
  }
  tab->table->status=0;
6280
  tab->read_record.read_record=join_read_prev;
unknown's avatar
unknown committed
6281 6282 6283 6284
  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
6285 6286
  if (!table->file->inited)
    table->file->ha_index_init(tab->index);
6287 6288
  if ((error= tab->table->file->index_last(tab->table->record[0])))
    return report_error(table, error);
unknown's avatar
unknown committed
6289 6290 6291
  return 0;
}

6292

unknown's avatar
unknown committed
6293
static int
6294
join_read_prev(READ_RECORD *info)
unknown's avatar
unknown committed
6295
{
6296 6297 6298
  int error;
  if ((error= info->file->index_prev(info->record)))
    return report_error(info->table, error);
unknown's avatar
unknown committed
6299 6300 6301
  return 0;
}

6302

unknown's avatar
unknown committed
6303 6304 6305 6306 6307 6308
static int
join_ft_read_first(JOIN_TAB *tab)
{
  int error;
  TABLE *table= tab->table;

unknown's avatar
unknown committed
6309 6310
  if (!table->file->inited)
    table->file->ha_index_init(tab->ref.key);
unknown's avatar
unknown committed
6311
#if NOT_USED_YET
unknown's avatar
unknown committed
6312
  if (cp_buffer_from_ref(&tab->ref))       // as ft-key doesn't use store_key's
unknown's avatar
unknown committed
6313
    return -1;                             // see also FT_SELECT::init()
unknown's avatar
unknown committed
6314
#endif
6315
  table->file->ft_init();
unknown's avatar
unknown committed
6316

6317 6318
  if ((error= table->file->ft_read(table->record[0])))
    return report_error(table, error);
unknown's avatar
unknown committed
6319 6320 6321 6322 6323 6324
  return 0;
}

static int
join_ft_read_next(READ_RECORD *info)
{
6325 6326 6327
  int error;
  if ((error= info->file->ft_read(info->table->record[0])))
    return report_error(info->table, error);
unknown's avatar
unknown committed
6328 6329 6330 6331
  return 0;
}


6332 6333 6334 6335 6336 6337 6338 6339 6340 6341
/*
  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 */
6342
  *tab->ref.null_ref_key= 0;			// Clear null byte
6343 6344 6345 6346
  if ((res= join_read_always_key(tab)) >= 0)
    return res;

  /* Then read key with null value */
6347
  *tab->ref.null_ref_key= 1;			// Set null byte
6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360
  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 */
6361
  if (*tab->ref.null_ref_key)
6362
    return -1;					// All keys read
6363 6364
  *tab->ref.null_ref_key= 1;			// Set null byte
  return safe_index_read(tab);			// then read null keys
6365 6366 6367
}


unknown's avatar
unknown committed
6368
/*****************************************************************************
6369 6370 6371
  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
6372 6373
*****************************************************************************/

6374
/* ARGSUSED */
unknown's avatar
unknown committed
6375 6376 6377 6378 6379 6380 6381 6382
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;
6383
    if (join->having && join->having->val_int() == 0)
unknown's avatar
unknown committed
6384
      DBUG_RETURN(0);				// Didn't match having
6385
    error=0;
unknown's avatar
unknown committed
6386 6387
    if (join->procedure)
      error=join->procedure->send_row(*join->fields);
unknown's avatar
unknown committed
6388
    else if (join->do_send_rows)
unknown's avatar
unknown committed
6389 6390 6391
      error=join->result->send_data(*join->fields);
    if (error)
      DBUG_RETURN(-1); /* purecov: inspected */
6392
    if (++join->send_records >= join->unit->select_limit_cnt &&
unknown's avatar
unknown committed
6393
	join->do_send_rows)
6394 6395 6396
    {
      if (join->select_options & OPTION_FOUND_ROWS)
      {
6397
	JOIN_TAB *jt=join->join_tab;
6398
	if ((join->tables == 1) && !join->tmp_table && !join->sort_and_group
6399
	    && !join->send_group_parts && !join->having && !jt->select_cond &&
6400
	    !(jt->select && jt->select->quick) &&
unknown's avatar
unknown committed
6401 6402
	    !(jt->table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
            (jt->ref.key < 0))
6403
	{
6404
	  /* Join over all rows in table;  Return number of found rows */
6405 6406
	  TABLE *table=jt->table;

6407
	  join->select_options ^= OPTION_FOUND_ROWS;
unknown's avatar
unknown committed
6408 6409
	  if (table->sort.record_pointers ||
	      (table->sort.io_cache && my_b_inited(table->sort.io_cache)))
6410 6411
	  {
	    /* Using filesort */
unknown's avatar
unknown committed
6412
	    join->send_records= table->sort.found_records;
6413 6414 6415 6416 6417 6418
	  }
	  else
	  {
	    table->file->info(HA_STATUS_VARIABLE);
	    join->send_records = table->file->records;
	  }
6419 6420 6421
	}
	else 
	{
6422
	  join->do_send_rows= 0;
unknown's avatar
unknown committed
6423 6424
	  if (join->unit->fake_select_lex)
	    join->unit->fake_select_lex->select_limit= HA_POS_ERROR;
6425 6426
	  DBUG_RETURN(0);
	}
6427
      }
unknown's avatar
unknown committed
6428
      DBUG_RETURN(-3);				// Abort nicely
6429
    }
unknown's avatar
unknown committed
6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456
  }
  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)
      {
6457
	int error=0;
unknown's avatar
unknown committed
6458 6459
	if (join->procedure)
	{
6460
	  if (join->having && join->having->val_int() == 0)
unknown's avatar
unknown committed
6461
	    error= -1;				// Didn't satisfy having
6462 6463 6464 6465 6466 6467
 	  else
	  {
	    if (join->do_send_rows)
	      error=join->procedure->send_row(*join->fields) ? 1 : 0;
	    join->send_records++;
	  }
unknown's avatar
unknown committed
6468 6469 6470 6471 6472 6473
	  if (end_of_records && join->procedure->end_of_records())
	    error= 1;				// Fatal error
	}
	else
	{
	  if (!join->first_record)
6474 6475
	  {
	    /* No matching rows for group function */
6476
	    join->clear();
6477
	  }
6478
	  if (join->having && join->having->val_int() == 0)
unknown's avatar
unknown committed
6479
	    error= -1;				// Didn't satisfy having
6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490
	  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
6491 6492 6493
	}
	if (error > 0)
	  DBUG_RETURN(-1);			/* purecov: inspected */
6494 6495
	if (end_of_records)
	  DBUG_RETURN(0);
6496
	if (join->send_records >= join->unit->select_limit_cnt &&
6497 6498 6499 6500 6501
	    join->do_send_rows)
	{
	  if (!(join->select_options & OPTION_FOUND_ROWS))
	    DBUG_RETURN(-3);				// Abort nicely
	  join->do_send_rows=0;
6502
	  join->unit->select_limit_cnt = HA_POS_ERROR;
6503
        }
unknown's avatar
unknown committed
6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515
      }
    }
    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);
6516 6517
      if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
	DBUG_RETURN(-1);
unknown's avatar
unknown committed
6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547
      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
  {
    my_error(ER_SERVER_SHUTDOWN,MYF(0));	/* purecov: inspected */
    DBUG_RETURN(-2);				/* purecov: inspected */
  }
  if (!end_of_records)
  {
    copy_fields(&join->tmp_table_param);
unknown's avatar
unknown committed
6548
    copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
6549

6550
#ifdef TO_BE_DELETED
unknown's avatar
unknown committed
6551 6552 6553 6554 6555 6556 6557 6558 6559
    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)
	{
6560
	  Field *field=item->get_tmp_table_field();
6561
	  field->ptr[-1]= (byte) (field->is_null() ? 1 : 0);
unknown's avatar
unknown committed
6562 6563 6564
	}
      }
    }
6565
#endif
unknown's avatar
unknown committed
6566 6567
    if (!join->having || join->having->val_int())
    {
unknown's avatar
unknown committed
6568
      join->found_records++;
unknown's avatar
unknown committed
6569 6570
      if ((error=table->file->write_row(table->record[0])))
      {
unknown's avatar
unknown committed
6571 6572 6573
	if (error == HA_ERR_FOUND_DUPP_KEY ||
	    error == HA_ERR_FOUND_DUPP_UNIQUE)
	  goto end;
unknown's avatar
unknown committed
6574 6575
	if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
				    error,1))
6576
	  DBUG_RETURN(-1);			// Not a table_is_full error
unknown's avatar
unknown committed
6577
	table->uniques=0;			// To ensure rows are the same
6578
      }
unknown's avatar
unknown committed
6579
      if (++join->send_records >= join->tmp_table_param.end_write_records &&
6580 6581 6582 6583 6584
	  join->do_send_rows)
      {
	if (!(join->select_options & OPTION_FOUND_ROWS))
	  DBUG_RETURN(-3);
	join->do_send_rows=0;
6585
	join->unit->select_limit_cnt = HA_POS_ERROR;
6586
	DBUG_RETURN(0);
unknown's avatar
unknown committed
6587 6588 6589
      }
    }
  }
unknown's avatar
unknown committed
6590
end:
unknown's avatar
unknown committed
6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613
  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
  {
    my_error(ER_SERVER_SHUTDOWN,MYF(0));	/* purecov: inspected */
    DBUG_RETURN(-2);				/* purecov: inspected */
  }

unknown's avatar
unknown committed
6614
  join->found_records++;
unknown's avatar
unknown committed
6615 6616 6617 6618 6619 6620
  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);
unknown's avatar
unknown committed
6621 6622 6623
#ifdef EMBEDDED_LIBRARY
    join->thd->net.last_errno= 0;
#endif
6624
    /* Store in the used key if the field was 0 */
unknown's avatar
unknown committed
6625
    if (item->maybe_null)
6626
      group->buff[-1]=item->null_value ? 1 : 0;
unknown's avatar
unknown committed
6627 6628 6629 6630 6631
  }
  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
6632
    restore_record(table,record[1]);
unknown's avatar
unknown committed
6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650
    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
6651
  copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
6652 6653
  if ((error=table->file->write_row(table->record[0])))
  {
unknown's avatar
unknown committed
6654 6655
    if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
				error, 0))
unknown's avatar
unknown committed
6656 6657
      DBUG_RETURN(-1);				// Not a table_is_full error
    /* Change method to update rows */
unknown's avatar
unknown committed
6658
    table->file->ha_index_init(0);
unknown's avatar
unknown committed
6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684
    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
  {
    my_error(ER_SERVER_SHUTDOWN,MYF(0));	/* purecov: inspected */
    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
6685
  copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700

  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
6701
    restore_record(table,record[1]);
unknown's avatar
unknown committed
6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738
    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
    my_error(ER_SERVER_SHUTDOWN,MYF(0));	/* purecov: inspected */
    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)
6739 6740
	{
	  /* No matching rows for group function */
6741
	  join->clear();
6742
	}
unknown's avatar
unknown committed
6743 6744 6745 6746 6747
	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
6748
	    if (create_myisam_from_heap(join->thd, table,
unknown's avatar
unknown committed
6749
					&join->tmp_table_param,
unknown's avatar
unknown committed
6750
					error, 0))
6751
	      DBUG_RETURN(-1);			// Not a table_is_full error
unknown's avatar
unknown committed
6752 6753 6754 6755 6756 6757 6758 6759 6760 6761
	  }
	  else
	    join->send_records++;
	}
	if (end_of_records)
	  DBUG_RETURN(0);
      }
    }
    else
    {
6762 6763
      if (end_of_records)
	DBUG_RETURN(0);
unknown's avatar
unknown committed
6764 6765 6766 6767 6768 6769
      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
6770
      copy_funcs(join->tmp_table_param.items_to_copy);
6771 6772
      if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
	DBUG_RETURN(-1);
unknown's avatar
unknown committed
6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786
      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);
}


/*****************************************************************************
6787 6788 6789 6790 6791
  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
6792 6793 6794 6795 6796 6797 6798
*****************************************************************************/

/* 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;
6799 6800
  // 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
6801 6802
  {
    Item *ref_item=part_of_refkey(field->table,field);
6803
    if (ref_item && ref_item->eq(right_item,1))
unknown's avatar
unknown committed
6804 6805
    {
      if (right_item->type() == Item::FIELD_ITEM)
6806 6807
	return (field->eq_def(((Item_field *) right_item)->field));
      if (right_item->const_item() && !(right_item->is_null()))
unknown's avatar
unknown committed
6808
      {
6809 6810 6811
	/*
	  We can remove binary fields and numerical fields except float,
	  as float comparison isn't 100 % secure
unknown's avatar
unknown committed
6812
	  We have to keep binary strings to be able to check for end spaces
6813
	*/
unknown's avatar
unknown committed
6814
	if (field->binary() &&
unknown's avatar
unknown committed
6815 6816
	    field->real_type() != FIELD_TYPE_STRING &&
	    field->real_type() != FIELD_TYPE_VAR_STRING &&
unknown's avatar
unknown committed
6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828
	    (field->type() != FIELD_TYPE_FLOAT || field->decimals() == 0))
	{
	  return !store_val_in_field(field,right_item);
	}
      }
    }
  }
  return 0;					// keep test
}


static COND *
6829
make_cond_for_table(COND *cond, table_map tables, table_map used_table)
unknown's avatar
unknown committed
6830 6831 6832 6833 6834 6835 6836
{
  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)
    {
6837
      /* Create new top level AND item */
unknown's avatar
unknown committed
6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854
      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
unknown committed
6855 6856 6857 6858 6859 6860 6861 6862
	/*
	  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 &
	  tables;
unknown's avatar
unknown committed
6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879
	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
unknown committed
6880 6881 6882 6883 6884 6885
      /*
	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;
6886
      new_cond->top_level_item();
unknown's avatar
unknown committed
6887 6888 6889 6890 6891
      return new_cond;
    }
  }

  /*
6892 6893 6894
    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
6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925
  */

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

unknown's avatar
unknown committed
6929 6930 6931 6932 6933 6934 6935 6936
  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) &&
6937
	  !(key_part->key_part_flag & HA_PART_KEY_SEG))
unknown's avatar
unknown committed
6938 6939 6940 6941 6942 6943 6944
	return table->reginfo.join_tab->ref.items[part];
  }
  return (Item*) 0;
}


/*****************************************************************************
6945
  Test if one can use the key to resolve ORDER BY
6946 6947 6948 6949 6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961 6962

  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
6963 6964
*****************************************************************************/

unknown's avatar
unknown committed
6965 6966
static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
				uint *used_key_parts)
unknown's avatar
unknown committed
6967 6968 6969 6970 6971 6972
{
  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;
6973
  DBUG_ENTER("test_if_order_by_key");
unknown's avatar
unknown committed
6974 6975 6976 6977 6978 6979 6980 6981 6982 6983

  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()
    */
6984 6985 6986
    for (; const_key_parts & 1 ; const_key_parts>>= 1)
      key_part++; 

unknown's avatar
unknown committed
6987
    if (key_part == key_part_end || key_part->field != field)
6988
      DBUG_RETURN(0);
unknown's avatar
unknown committed
6989 6990

    /* set flag to 1 if we can use read-next on key, else to -1 */
6991 6992
    flag= ((order->asc == !(key_part->key_part_flag & HA_REVERSE_SORT)) ?
           1 : -1);
unknown's avatar
unknown committed
6993
    if (reverse && flag != reverse)
6994
      DBUG_RETURN(0);
unknown's avatar
unknown committed
6995 6996 6997
    reverse=flag;				// Remember if reverse
    key_part++;
  }
6998 6999 7000 7001
  *used_key_parts= (uint) (key_part - table->key_info[idx].key_part);
  if (reverse == -1 && !(table->file->index_flags(idx, *used_key_parts-1, 1) &
                         HA_READ_PREV))
    reverse= 0;                                 // Index can't be used
7002
  DBUG_RETURN(reverse);
unknown's avatar
unknown committed
7003 7004
}

7005

unknown's avatar
unknown committed
7006
static uint find_shortest_key(TABLE *table, const key_map *usable_keys)
unknown's avatar
unknown committed
7007 7008 7009
{
  uint min_length= (uint) ~0;
  uint best= MAX_KEY;
unknown's avatar
unknown committed
7010
  if (!usable_keys->is_clear_all())
unknown's avatar
unknown committed
7011
  {
unknown's avatar
unknown committed
7012
    for (uint nr=0; nr < table->keys ; nr++)
unknown's avatar
unknown committed
7013
    {
unknown's avatar
unknown committed
7014
      if (usable_keys->is_set(nr))
unknown's avatar
unknown committed
7015
      {
7016 7017 7018 7019 7020
        if (table->key_info[nr].key_length < min_length)
        {
          min_length=table->key_info[nr].key_length;
          best=nr;
        }
unknown's avatar
unknown committed
7021 7022 7023 7024 7025 7026
      }
    }
  }
  return best;
}

7027
/*
7028 7029
  Test if a second key is the subkey of the first one.

7030 7031
  SYNOPSIS
    is_subkey()
7032 7033 7034 7035
    key_part		First key parts
    ref_key_part	Second key parts
    ref_key_part_end	Last+1 part of the second key

7036 7037
  NOTE
    Second key MUST be shorter than the first one.
7038

7039
  RETURN
7040 7041
    1	is a subkey
    0	no sub key
7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054
*/

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

/*
7055 7056
  Test if we can use one of the 'usable_keys' instead of 'ref' key for sorting

7057 7058
  SYNOPSIS
    test_if_subkey()
7059 7060 7061
    ref			Number of key, used for WHERE clause
    usable_keys		Keys for testing

7062
  RETURN
7063 7064
    MAX_KEY			If we can't use other key
    the number of found key	Otherwise
7065 7066 7067
*/

static uint
unknown's avatar
unknown committed
7068
test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
7069
	       const key_map *usable_keys)
7070 7071 7072 7073 7074 7075 7076
{
  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;
7077

unknown's avatar
unknown committed
7078
  for (nr= 0 ; nr < table->keys ; nr++)
7079
  {
7080
    if (usable_keys->is_set(nr) &&
7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092
	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
7093

7094 7095 7096 7097 7098 7099 7100 7101 7102 7103
/*
  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
7104 7105

static bool
7106 7107
test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
			bool no_changes)
unknown's avatar
unknown committed
7108 7109
{
  int ref_key;
unknown's avatar
unknown committed
7110
  uint ref_key_parts;
unknown's avatar
unknown committed
7111 7112 7113 7114
  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
7115
  LINT_INIT(ref_key_parts);
unknown's avatar
unknown committed
7116 7117

  /* Check which keys can be used to resolve ORDER BY */
7118
  usable_keys.set_all();
unknown's avatar
unknown committed
7119 7120 7121 7122
  for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
  {
    if ((*tmp_order->item)->type() != Item::FIELD_ITEM)
    {
7123
      usable_keys.clear_all();
7124
      DBUG_RETURN(0);
unknown's avatar
unknown committed
7125
    }
7126 7127
    usable_keys.intersect(((Item_field*) (*tmp_order->item))->
			  field->part_of_sortkey);
unknown's avatar
unknown committed
7128
    if (usable_keys.is_clear_all())
7129
      DBUG_RETURN(0);					// No usable keys
unknown's avatar
unknown committed
7130 7131 7132
  }

  ref_key= -1;
7133
  /* Test if constant range in WHERE */
7134
  if (tab->ref.key >= 0 && tab->ref.key_parts)
unknown's avatar
unknown committed
7135 7136 7137
  {
    ref_key=	   tab->ref.key;
    ref_key_parts= tab->ref.key_parts;
7138 7139
    if (tab->type == JT_REF_OR_NULL)
      DBUG_RETURN(0);
unknown's avatar
unknown committed
7140
  }
unknown's avatar
unknown committed
7141
  else if (select && select->quick)		// Range found by opt_range
unknown's avatar
unknown committed
7142 7143 7144 7145
  {
    ref_key=	   select->quick->index;
    ref_key_parts= select->quick->used_key_parts;
  }
unknown's avatar
unknown committed
7146 7147 7148

  if (ref_key >= 0)
  {
7149 7150 7151
    /*
      We come here when there is a REF key.
    */
7152
    int order_direction;
unknown's avatar
unknown committed
7153
    uint used_key_parts;
7154
    if (!usable_keys.is_set(ref_key))
7155 7156 7157 7158
    {
      /*
	We come here when ref_key is not among usable_keys
      */
unknown's avatar
unknown committed
7159 7160 7161 7162 7163
      uint new_ref_key;
      /*
	If using index only read, only consider other possible index only
	keys
      */
7164
      if (table->used_keys.is_set(ref_key))
7165
	usable_keys.intersect(table->used_keys);
unknown's avatar
unknown committed
7166
      if ((new_ref_key= test_if_subkey(order, table, ref_key, ref_key_parts,
7167
				       &usable_keys)) < MAX_KEY)
7168
      {
unknown's avatar
unknown committed
7169
	/* Found key that can be used to retrieve data in sorted order */
7170 7171
	if (tab->ref.key >= 0)
	{
unknown's avatar
unknown committed
7172
	  tab->ref.key= new_ref_key;
7173 7174 7175
	}
	else
	{
unknown's avatar
unknown committed
7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191
          /*
            The range optimizer constructed QUICK_RANGE for ref_key, and
            we want to use instead new_ref_key as the index. We can't
            just change the index of the quick select, because this may
            result in an incosistent QUICK_SELECT object. Below we
            create a new QUICK_SELECT from scratch so that all its
            parameres are set correctly by the range optimizer.
           */
          key_map new_ref_key_map;
          new_ref_key_map.clear_all();  /* Force the creation of quick select */
          new_ref_key_map.set_bit(new_ref_key); /* only for new_ref_key.      */

          if (select->test_quick_select(tab->join->thd, new_ref_key_map, 0,
                                        (tab->join->select_options & OPTION_FOUND_ROWS) ?
                                        HA_POS_ERROR : tab->join->unit->select_limit_cnt) <= 0)
            DBUG_RETURN(0);
7192
	}
unknown's avatar
unknown committed
7193
        ref_key= new_ref_key;
7194
      }
7195
    }
unknown's avatar
unknown committed
7196
    /* Check if we get the rows in requested sorted order by using the key */
7197
    if (usable_keys.is_set(ref_key) &&
unknown's avatar
unknown committed
7198 7199
	(order_direction = test_if_order_by_key(order,table,ref_key,
						&used_key_parts)))
7200
    {
7201
      if (order_direction == -1)		// If ORDER BY ... DESC
7202
      {
unknown's avatar
unknown committed
7203 7204
	if (select && select->quick)
	{
7205 7206 7207 7208 7209
	  /*
	    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
7210
	  {
7211 7212 7213 7214 7215 7216 7217 7218 7219
	    // ORDER BY range_key DESC
	    QUICK_SELECT_DESC *tmp=new QUICK_SELECT_DESC(select->quick,
							 used_key_parts);
	    if (!tmp || tmp->error)
	    {
	      delete tmp;
	      DBUG_RETURN(0);		// Reverse sort not supported
	    }
	    select->quick=tmp;
unknown's avatar
unknown committed
7220 7221 7222 7223 7224 7225 7226
	  }
	  DBUG_RETURN(1);
	}
	if (tab->ref.key_parts < used_key_parts)
	{
	  /*
	    SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
7227 7228 7229

	    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
7230
	  */
7231 7232 7233
	  tab->read_first_record=       join_read_last_key;
	  tab->read_record.read_record= join_read_prev_same;
	  /* fall through */
unknown's avatar
unknown committed
7234
	}
7235
      }
7236 7237
      else if (select && select->quick)
	  select->quick->sorted= 1;
unknown's avatar
unknown committed
7238
      DBUG_RETURN(1);			/* No need to sort */
7239
    }
unknown's avatar
unknown committed
7240 7241 7242 7243 7244 7245
  }
  else
  {
    /* check if we can use a key to resolve the group */
    /* Tables using JT_NEXT are handled here */
    uint nr;
unknown's avatar
unknown committed
7246
    key_map keys;
unknown's avatar
unknown committed
7247 7248 7249 7250 7251 7252 7253

    /*
      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)
unknown's avatar
unknown committed
7254 7255 7256
    {
      keys= *table->file->keys_to_use_for_scanning();
      keys.merge(table->used_keys);
unknown's avatar
unknown committed
7257

unknown's avatar
unknown committed
7258
      /*
unknown's avatar
unknown committed
7259
	We are adding here also the index specified in FORCE INDEX clause, 
unknown's avatar
unknown committed
7260
	if any.
unknown's avatar
unknown committed
7261
        This is to allow users to use index in ORDER BY.
unknown's avatar
unknown committed
7262 7263 7264 7265
      */
      if (table->force_index) 
	keys.merge(table->keys_in_use_for_query);
      keys.intersect(usable_keys);
7266 7267
    }
    else
7268
      keys= usable_keys;
unknown's avatar
unknown committed
7269

unknown's avatar
unknown committed
7270
    for (nr=0; nr < table->keys ; nr++)
unknown's avatar
unknown committed
7271
    {
7272
      uint not_used;
7273
      if (keys.is_set(nr))
unknown's avatar
unknown committed
7274 7275
      {
	int flag;
unknown's avatar
unknown committed
7276
	if ((flag= test_if_order_by_key(order, table, nr, &not_used)))
unknown's avatar
unknown committed
7277
	{
7278 7279 7280
	  if (!no_changes)
	  {
	    tab->index=nr;
7281 7282
	    tab->read_first_record=  (flag > 0 ? join_read_first:
				      join_read_last);
7283
	    tab->type=JT_NEXT;	// Read with index_first(), index_next()
7284
	    if (table->used_keys.is_set(nr))
unknown's avatar
unknown committed
7285 7286 7287 7288
	    {
	      table->key_read=1;
	      table->file->extra(HA_EXTRA_KEYREAD);
	    }
7289
	  }
unknown's avatar
unknown committed
7290 7291 7292 7293 7294 7295 7296 7297
	  DBUG_RETURN(1);
	}
      }
    }
  }
  DBUG_RETURN(0);				// Can't use index.
}

unknown's avatar
unknown committed
7298

unknown's avatar
unknown committed
7299
/*
unknown's avatar
unknown committed
7300
  If not selecting by given key, create an index how records should be read
unknown's avatar
unknown committed
7301 7302 7303 7304 7305 7306 7307 7308

  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
7309
		        Used to decide if we should use index or not
unknown's avatar
unknown committed
7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324


  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
7325

unknown's avatar
unknown committed
7326
static int
7327
create_sort_index(THD *thd, JOIN *join, ORDER *order,
unknown's avatar
unknown committed
7328
		  ha_rows filesort_limit, ha_rows select_limit)
unknown's avatar
unknown committed
7329 7330 7331
{
  SORT_FIELD *sortorder;
  uint length;
7332
  ha_rows examined_rows;
7333 7334 7335
  TABLE *table;
  SQL_SELECT *select;
  JOIN_TAB *tab;
unknown's avatar
unknown committed
7336 7337
  DBUG_ENTER("create_sort_index");

7338 7339 7340 7341 7342 7343
  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;

7344
  if (test_if_skip_sort_order(tab,order,select_limit,0))
unknown's avatar
unknown committed
7345 7346 7347 7348
    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
7349 7350
  table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
                                             MYF(MY_WME | MY_ZEROFILL));
unknown's avatar
unknown committed
7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364 7365 7366 7367 7368 7369 7370 7371
  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;
      /* We can only use 'Only index' if quick key is same as ref_key */
      if (table->key_read && (uint) tab->ref.key != select->quick->index)
      {
	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.
7372 7373
	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
7374
      */
7375 7376 7377
      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
7378 7379 7380
	goto err;
    }
  }
7381 7382
  if (table->tmp_table)
    table->file->info(HA_STATUS_VARIABLE);	// Get record count
unknown's avatar
unknown committed
7383 7384
  table->sort.found_records=filesort(thd, table,sortorder, length,
                                     select, filesort_limit, &examined_rows);
unknown's avatar
merge  
unknown committed
7385
  tab->records= table->sort.found_records;	// For SQL_CALC_ROWS
7386 7387 7388 7389 7390
  if (select)
  {
    select->cleanup();				// filesort did select
    tab->select= 0;
  }
unknown's avatar
unknown committed
7391 7392 7393
  tab->select_cond=0;
  tab->type=JT_ALL;				// Read with normal read_record
  tab->read_first_record= join_init_read_record;
7394
  tab->join->examined_rows+=examined_rows;
unknown's avatar
unknown committed
7395 7396 7397 7398 7399
  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
7400
  DBUG_RETURN(table->sort.found_records == HA_POS_ERROR);
unknown's avatar
unknown committed
7401 7402 7403 7404
err:
  DBUG_RETURN(-1);
}

7405
/*
7406
  Add the HAVING criteria to table->select
7407 7408
*/

unknown's avatar
unknown committed
7409
#ifdef NOT_YET
7410 7411 7412 7413 7414 7415
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
7416
  DBUG_EXECUTE("where",print_where(*having,"having"););
7417 7418 7419 7420 7421 7422 7423 7424 7425
  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
7426 7427
      if (!(table->select->cond= new Item_cond_and(table->select->cond,
						   sort_table_cond)) ||
unknown's avatar
unknown committed
7428
	  table->select->cond->fix_fields(join->thd, join->tables_list,
7429
					  &table->select->cond))
7430 7431
	return 1;
    table->select_cond=table->select->cond;
7432
    table->select_cond->top_level_item();
7433 7434 7435 7436 7437 7438 7439
    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
7440
#endif
7441 7442


unknown's avatar
unknown committed
7443
/*****************************************************************************
7444 7445 7446 7447 7448
  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
7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482
*****************************************************************************/

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
7483
remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
unknown's avatar
unknown committed
7484 7485 7486 7487
{
  int error;
  ulong reclength,offset;
  uint field_count;
7488
  THD *thd= join->thd;
unknown's avatar
unknown committed
7489 7490 7491 7492 7493 7494 7495 7496 7497
  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
7498
  {
7499
    if (item->get_tmp_table_field() && ! item->const_item())
unknown's avatar
unknown committed
7500
      field_count++;
unknown's avatar
unknown committed
7501
  }
unknown's avatar
unknown committed
7502

7503 7504
  if (!field_count && !(join->select_options & OPTION_FOUND_ROWS)) 
  {                    // only const items with no OPTION_FOUND_ROWS
7505
    join->unit->select_limit_cnt= 1;		// Only send first row
unknown's avatar
unknown committed
7506 7507 7508
    DBUG_RETURN(0);
  }
  Field **first_field=entry->field+entry->fields - field_count;
7509 7510
  offset= field_count ? 
          entry->field[entry->fields - field_count]->offset() : 0;
unknown's avatar
unknown committed
7511 7512 7513 7514 7515 7516
  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
7517
       ((ALIGN_SIZE(reclength) + HASH_OVERHEAD) * entry->file->records <
7518
	thd->variables.sortbuff_size)))
unknown's avatar
unknown committed
7519 7520
    error=remove_dup_with_hash_index(join->thd, entry,
				     field_count, first_field,
7521
				     reclength, having);
unknown's avatar
unknown committed
7522
  else
7523 7524
    error=remove_dup_with_compare(join->thd, entry, first_field, offset,
				  having);
unknown's avatar
unknown committed
7525 7526 7527 7528 7529 7530 7531

  free_blobs(first_field);
  DBUG_RETURN(error);
}


static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
7532
				   ulong offset, Item *having)
unknown's avatar
unknown committed
7533 7534 7535
{
  handler *file=table->file;
  char *org_record,*new_record;
unknown's avatar
unknown committed
7536
  byte *record;
unknown's avatar
unknown committed
7537 7538 7539 7540
  int error;
  ulong reclength=table->reclength-offset;
  DBUG_ENTER("remove_dup_with_compare");

7541
  org_record=(char*) (record=table->record[0])+offset;
unknown's avatar
unknown committed
7542 7543
  new_record=(char*) table->record[1]+offset;

7544
  file->ha_rnd_init(1);
7545
  error=file->rnd_next(record);
unknown's avatar
unknown committed
7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561
  for (;;)
  {
    if (thd->killed)
    {
      my_error(ER_SERVER_SHUTDOWN,MYF(0));
      error=0;
      goto err;
    }
    if (error)
    {
      if (error == HA_ERR_RECORD_DELETED)
	continue;
      if (error == HA_ERR_END_OF_FILE)
	break;
      goto err;
    }
7562 7563 7564 7565
    if (having && !having->val_int())
    {
      if ((error=file->delete_row(record)))
	goto err;
7566
      error=file->rnd_next(record);
7567 7568
      continue;
    }
unknown's avatar
unknown committed
7569 7570
    if (copy_blobs(first_field))
    {
unknown's avatar
unknown committed
7571
      my_error(ER_OUTOFMEMORY,MYF(0));
unknown's avatar
unknown committed
7572 7573 7574 7575 7576 7577 7578 7579 7580
      error=0;
      goto err;
    }
    memcpy(new_record,org_record,reclength);

    /* Read through rest of file and mark duplicated rows deleted */
    bool found=0;
    for (;;)
    {
7581
      if ((error=file->rnd_next(record)))
unknown's avatar
unknown committed
7582 7583 7584 7585 7586 7587 7588 7589 7590
      {
	if (error == HA_ERR_RECORD_DELETED)
	  continue;
	if (error == HA_ERR_END_OF_FILE)
	  break;
	goto err;
      }
      if (compare_record(table, first_field) == 0)
      {
7591
	if ((error=file->delete_row(record)))
unknown's avatar
unknown committed
7592 7593 7594 7595 7596
	  goto err;
      }
      else if (!found)
      {
	found=1;
7597
	file->position(record);	// Remember position
unknown's avatar
unknown committed
7598 7599 7600 7601 7602
      }
    }
    if (!found)
      break;					// End of file
    /* Restart search on next row */
7603
    error=file->restart_rnd_next(record,file->ref);
unknown's avatar
unknown committed
7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623
  }

  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,
7624 7625
				      ulong key_length,
				      Item *having)
unknown's avatar
unknown committed
7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642
{
  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
7643

unknown's avatar
unknown committed
7644
  if (hash_init(&hash, &my_charset_bin, (uint) file->records, 0, 
unknown's avatar
unknown committed
7645
		key_length,(hash_get_key) 0, 0, 0))
unknown's avatar
unknown committed
7646 7647 7648 7649 7650 7651 7652 7653 7654 7655
  {
    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();
  }

7656
  file->ha_rnd_init(1);
unknown's avatar
unknown committed
7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673
  key_pos=key_buffer;
  for (;;)
  {
    if (thd->killed)
    {
      my_error(ER_SERVER_SHUTDOWN,MYF(0));
      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;
    }
7674 7675 7676 7677 7678
    if (having && !having->val_int())
    {
      if ((error=file->delete_row(record)))
	goto err;
      continue;
7679
    }
unknown's avatar
unknown committed
7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694

    /* 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;
    }
7695
    else
unknown's avatar
SCRUM  
unknown committed
7696
      (void) my_hash_insert(&hash, key_pos-key_length);
unknown's avatar
unknown committed
7697 7698 7699 7700 7701
    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
7702
  (void) file->ha_rnd_end();
unknown's avatar
unknown committed
7703 7704 7705 7706 7707 7708
  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
7709
  (void) file->ha_rnd_end();
unknown's avatar
unknown committed
7710 7711 7712 7713 7714 7715
  if (error)
    file->print_error(error,MYF(0));
  DBUG_RETURN(1);
}


unknown's avatar
unknown committed
7716
SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
unknown's avatar
unknown committed
7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735
{
  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())
7736
      pos->field= ((Item_sum*) order->item[0])->get_tmp_table_field();
unknown's avatar
unknown committed
7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750
    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);
}


/*****************************************************************************
7751 7752 7753 7754
  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
7755 7756 7757 7758 7759 7760 7761 7762 7763
******************************************************************************/

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;
7764
  JOIN_TAB *join_tab;
unknown's avatar
unknown committed
7765 7766 7767 7768 7769
  DBUG_ENTER("join_init_cache");

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

7770 7771
  join_tab=tables;
  for (i=0 ; i < table_count ; i++,join_tab++)
unknown's avatar
unknown committed
7772
  {
7773 7774 7775 7776
    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
7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815
  }
  if (!(cache->field=(CACHE_FIELD*)
	sql_alloc(sizeof(CACHE_FIELD)*(cache->fields+table_count*2)+(blobs+1)*
		  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;
7816
      copy->length=tables[i].table->null_bytes;
unknown's avatar
unknown committed
7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838
      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 */
7839
  size=max(thd->variables.join_buff_size, cache->length);
unknown's avatar
unknown committed
7840 7841 7842
  if (!(cache->buff=(uchar*) my_malloc(size,MYF(0))))
    DBUG_RETURN(1);				/* Don't use cache */ /* purecov: inspected */
  cache->end=cache->buff+size;
7843
  reset_cache_write(cache);
unknown's avatar
unknown committed
7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879
  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;

  /*
7880
    There is room in cache. Put record there
unknown's avatar
unknown committed
7881 7882 7883 7884 7885 7886 7887 7888
  */
  cache->records++;
  for (copy=cache->field ; copy < end_field; copy++)
  {
    if (copy->blob_field)
    {
      if (last_record)
      {
unknown's avatar
unknown committed
7889 7890
	copy->blob_field->get_image((char*) pos,copy->length+sizeof(char*), 
				    copy->blob_field->charset());
unknown's avatar
unknown committed
7891 7892 7893 7894
	pos+=copy->length+sizeof(char*);
      }
      else
      {
unknown's avatar
unknown committed
7895 7896
	copy->blob_field->get_image((char*) pos,copy->length, // blob length
				    copy->blob_field->charset());
unknown's avatar
unknown committed
7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926
	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
7927
reset_cache_read(JOIN_CACHE *cache)
unknown's avatar
unknown committed
7928 7929 7930
{
  cache->record_nr=0;
  cache->pos=cache->buff;
7931 7932 7933 7934 7935 7936 7937 7938
}


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
7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960
}


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
7961 7962
	copy->blob_field->set_image((char*) pos,copy->length+sizeof(char*),
				    copy->blob_field->charset());
unknown's avatar
unknown committed
7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016
	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;
}


/*****************************************************************************
8017
  Group and order functions
unknown's avatar
unknown committed
8018 8019 8020
*****************************************************************************/

/*
8021 8022 8023
  Find order/group item in requested columns and change the item to point at
  it. If item doesn't exists, add it first in the field list
  Return 0 if ok.
unknown's avatar
unknown committed
8024 8025 8026
*/

static int
8027 8028
find_order_in_list(THD *thd, Item **ref_pointer_array,
		   TABLE_LIST *tables,ORDER *order, List<Item> &fields,
unknown's avatar
unknown committed
8029 8030
		   List<Item> &all_fields)
{
8031 8032
  Item *it= *order->item;
  if (it->type() == Item::INT_ITEM)
unknown's avatar
unknown committed
8033
  {						/* Order by position */
8034
    uint count= (uint) it->val_int();
unknown's avatar
unknown committed
8035
    if (!count || count > fields.elements)
unknown's avatar
unknown committed
8036 8037
    {
      my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),
8038
		      MYF(0), it->full_name(), thd->where);
unknown's avatar
unknown committed
8039 8040
      return 1;
    }
8041 8042
    order->item= ref_pointer_array + count-1;
    order->in_field_list= 1;
unknown's avatar
unknown committed
8043 8044
    return 0;
  }
8045
  uint counter;
8046 8047 8048
  bool unaliased;
  Item **item= find_item_in_list(it, fields, &counter,
                                 REPORT_EXCEPT_NOT_FOUND, &unaliased);
8049 8050 8051
  if (!item)
    return 1;

8052
  if (item != (Item **)not_found_item)
unknown's avatar
unknown committed
8053
  {
8054 8055 8056 8057 8058 8059 8060 8061
    /*
      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).
    */
    if (unaliased && !it->fixed && it->fix_fields(thd, tables, order->item))
      return 1;

8062
    order->item= ref_pointer_array + counter;
unknown's avatar
unknown committed
8063 8064 8065
    order->in_field_list=1;
    return 0;
  }
8066

unknown's avatar
unknown committed
8067
  order->in_field_list=0;
8068
  /*
unknown's avatar
unknown committed
8069 8070 8071 8072
    We check it->fixed because Item_func_group_concat can put
    arguments for which fix_fields already was called.

    'it' reassigned in if condition because fix_field can change it.
8073 8074 8075 8076 8077
  */
  if (!it->fixed &&
      (it->fix_fields(thd, tables, order->item) ||
       (it= *order->item)->check_cols(1) ||
       thd->is_fatal_error))
8078
    return 1;					// Wrong field 
8079 8080 8081 8082
  uint el= all_fields.elements;
  all_fields.push_front(it);		        // Add new field to field list
  ref_pointer_array[el]= it;
  order->item= ref_pointer_array + el;
unknown's avatar
unknown committed
8083 8084 8085 8086
  return 0;
}

/*
8087 8088
  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
8089 8090
*/

8091 8092
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
8093 8094 8095 8096
{
  thd->where="order clause";
  for (; order; order=order->next)
  {
8097 8098
    if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
			   all_fields))
unknown's avatar
unknown committed
8099 8100 8101 8102 8103 8104
      return 1;
  }
  return 0;
}


unknown's avatar
unknown committed
8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127
/*
  Intitialize the GROUP BY list.

  SYNOPSIS
   setup_group()
   thd			Thread handler
   ref_pointer_array	We store references to all fields that was not in
			'fields' here.   
   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
8128
int
8129 8130 8131
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
8132 8133 8134 8135 8136
{
  *hidden_group_fields=0;
  if (!order)
    return 0;				/* Everything is ok */

8137
  if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
unknown's avatar
unknown committed
8138 8139 8140 8141 8142 8143 8144 8145 8146
  {
    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";
8147
  for (; order; order=order->next)
unknown's avatar
unknown committed
8148
  {
8149 8150
    if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
			   all_fields))
unknown's avatar
unknown committed
8151 8152 8153 8154 8155 8156 8157 8158 8159
      return 1;
    (*order->item)->marker=1;		/* Mark found */
    if ((*order->item)->with_sum_func)
    {
      my_printf_error(ER_WRONG_GROUP_FIELD, ER(ER_WRONG_GROUP_FIELD),MYF(0),
		      (*order->item)->full_name());
      return 1;
    }
  }
8160
  if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
unknown's avatar
unknown committed
8161 8162 8163 8164 8165 8166 8167
  {
    /* Don't allow one to use fields that is not used in GROUP BY */
    Item *item;
    List_iterator<Item> li(fields);

    while ((item=li++))
    {
8168 8169
      if (item->type() != Item::SUM_FUNC_ITEM && !item->marker &&
	  !item->const_item())
unknown's avatar
unknown committed
8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183
      {
	my_printf_error(ER_WRONG_FIELD_WITH_GROUP,
			ER(ER_WRONG_FIELD_WITH_GROUP),
			MYF(0),item->full_name());
	return 1;
      }
    }
  }
  if (org_fields != all_fields.elements)
    *hidden_group_fields=1;			// group fields is not used
  return 0;
}

/*
8184
  Add fields with aren't used at start of field list. Return FALSE if ok
unknown's avatar
unknown committed
8185 8186 8187 8188 8189 8190 8191 8192 8193 8194
*/

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...
8195
  uint counter;
8196
  bool not_used;
unknown's avatar
unknown committed
8197
  for (; new_field ; new_field= new_field->next)
unknown's avatar
unknown committed
8198
  {
8199
    if ((item= find_item_in_list(*new_field->item, fields, &counter,
8200
				 IGNORE_ERRORS, &not_used)))
unknown's avatar
unknown committed
8201 8202 8203 8204
      new_field->item=item;			/* Change to shared Item */
    else
    {
      thd->where="procedure list";
unknown's avatar
unknown committed
8205
      if ((*new_field->item)->fix_fields(thd, tables, new_field->item))
unknown's avatar
unknown committed
8206 8207 8208 8209 8210 8211 8212 8213 8214
	DBUG_RETURN(1); /* purecov: inspected */
      all_fields.push_front(*new_field->item);
      new_field->item=all_fields.head_ref();
    }
  }
  DBUG_RETURN(0);
}

/*
8215 8216 8217
  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
8218 8219 8220
*/

static ORDER *
8221 8222
create_distinct_group(THD *thd, ORDER *order_list, List<Item> &fields, 
		      bool *all_order_by_fields_used)
unknown's avatar
unknown committed
8223 8224 8225 8226 8227
{
  List_iterator<Item> li(fields);
  Item *item;
  ORDER *order,*group,**prev;

8228
  *all_order_by_fields_used= 1;
unknown's avatar
unknown committed
8229 8230 8231 8232 8233 8234 8235 8236
  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)
    {
8237
      ORDER *ord=(ORDER*) thd->memdup((char*) order,sizeof(ORDER));
unknown's avatar
unknown committed
8238 8239 8240 8241 8242 8243
      if (!ord)
	return 0;
      *prev=ord;
      prev= &ord->next;
      (*ord->item)->marker=1;
    }
8244 8245
    else
      *all_order_by_fields_used= 0;
unknown's avatar
unknown committed
8246 8247 8248 8249 8250 8251 8252 8253 8254
  }

  li.rewind();
  while ((item=li++))
  {
    if (item->const_item() || item->with_sum_func)
      continue;
    if (!item->marker)
    {
8255
      ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER));
unknown's avatar
unknown committed
8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269
      if (!ord)
	return 0;
      ord->item=li.ref();
      ord->asc=1;
      *prev=ord;
      prev= &ord->next;
    }
  }
  *prev=0;
  return group;
}


/*****************************************************************************
8270
  Update join with count of the different type of fields
unknown's avatar
unknown committed
8271 8272 8273
*****************************************************************************/

void
unknown's avatar
unknown committed
8274 8275
count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
		  bool reset_with_sum_func)
unknown's avatar
unknown committed
8276 8277 8278 8279
{
  List_iterator<Item> li(fields);
  Item *field;

8280
  param->field_count=param->sum_func_count=param->func_count=
unknown's avatar
unknown committed
8281
    param->hidden_field_count=0;
unknown's avatar
unknown committed
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
  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
8307
    {
unknown's avatar
unknown committed
8308
      param->func_count++;
unknown's avatar
unknown committed
8309 8310 8311
      if (reset_with_sum_func)
	field->with_sum_func=0;
    }
unknown's avatar
unknown committed
8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326
  }
}


/*
  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)
  {
8327
    if ((*a->item)->eq(*b->item,1))
unknown's avatar
unknown committed
8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353
      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)
  {
8354
    if (!(*a->item)->eq(*b->item,1))
unknown's avatar
unknown committed
8355 8356 8357
      DBUG_RETURN(0);
    map|=a->item[0]->used_tables();
  }
unknown's avatar
unknown committed
8358
  if (!map || (map & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT)))
unknown's avatar
unknown committed
8359 8360
    DBUG_RETURN(0);

8361
  for (; !(map & tables->table->map) ; tables=tables->next) ;
unknown's avatar
unknown committed
8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373
  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)
{
8374 8375
  uint key_length=0, parts=0, null_parts=0;

unknown's avatar
unknown committed
8376 8377 8378 8379
  if (group)
    join->group= 1;
  for (; group ; group=group->next)
  {
8380
    Field *field=(*group->item)->get_tmp_table_field();
unknown's avatar
unknown committed
8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395
    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)
8396
      null_parts++;
unknown's avatar
unknown committed
8397
  }
8398
  join->tmp_table_param.group_length=key_length+null_parts;
unknown's avatar
unknown committed
8399
  join->tmp_table_param.group_parts=parts;
8400
  join->tmp_table_param.group_null_parts=null_parts;
unknown's avatar
unknown committed
8401 8402
}

8403

8404
/*
8405
  allocate group fields or take prepared (cached)
8406

8407
  SYNOPSIS
8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419
    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)
{
8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431
  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);
8432
}
unknown's avatar
unknown committed
8433

8434

unknown's avatar
unknown committed
8435
/*
8436 8437
  Get a list of buffers for saveing last group
  Groups are saved in reverse order for easyer check loop
unknown's avatar
unknown committed
8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459
*/

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)
{
8460
  DBUG_ENTER("test_if_group_changed");
unknown's avatar
unknown committed
8461 8462 8463 8464 8465 8466 8467 8468 8469
  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;
  }
8470 8471
  DBUG_PRINT("info", ("idx: %d", idx));
  DBUG_RETURN(idx);
unknown's avatar
unknown committed
8472 8473 8474 8475
}


/*
8476
  Setup copy_fields to save fields at start of new group
unknown's avatar
unknown committed
8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495

  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
8496 8497 8498
*/

bool
8499 8500
setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
		  Item **ref_pointer_array,
unknown's avatar
unknown committed
8501 8502
		  List<Item> &res_selected_fields, List<Item> &res_all_fields,
		  uint elements, List<Item> &all_fields)
unknown's avatar
unknown committed
8503 8504
{
  Item *pos;
unknown's avatar
unknown committed
8505
  List_iterator_fast<Item> li(all_fields);
unknown's avatar
unknown committed
8506
  Copy_field *copy;
unknown's avatar
unknown committed
8507 8508 8509
  res_selected_fields.empty();
  res_all_fields.empty();
  List_iterator_fast<Item> itr(res_all_fields);
8510
  List<Item> extra_funcs;
unknown's avatar
unknown committed
8511
  uint i, border= all_fields.elements - elements;
unknown's avatar
unknown committed
8512
  DBUG_ENTER("setup_copy_fields");
unknown's avatar
unknown committed
8513 8514

  if (!(copy=param->copy_field= new Copy_field[param->field_count]))
8515
    goto err2;
unknown's avatar
unknown committed
8516 8517

  param->copy_funcs.empty();
8518
  for (i= 0; (pos= li++); i++)
unknown's avatar
unknown committed
8519 8520 8521
  {
    if (pos->type() == Item::FIELD_ITEM)
    {
8522
      Item_field *item;
8523
      if (!(item= new Item_field(thd, ((Item_field*) pos))))
8524 8525
	goto err;
      pos= item;
unknown's avatar
unknown committed
8526 8527
      if (item->field->flags & BLOB_FLAG)
      {
8528
	if (!(pos= new Item_copy_string(pos)))
unknown's avatar
unknown committed
8529
	  goto err;
8530 8531 8532 8533 8534 8535 8536 8537 8538 8539
       /*
         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
8540 8541
	  goto err;
      }
8542 8543 8544 8545 8546 8547 8548
      else
      {
	/* 
	   set up save buffer and change result_field to point at 
	   saved value
	*/
	Field *field= item->field;
unknown's avatar
unknown committed
8549
	item->result_field=field->new_field(thd->mem_root,field->table);
8550 8551 8552 8553 8554 8555 8556
	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
8557 8558
    }
    else if ((pos->type() == Item::FUNC_ITEM ||
8559 8560
	      pos->type() == Item::SUBSELECT_ITEM ||
	      pos->type() == Item::CACHE_ITEM ||
unknown's avatar
unknown committed
8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571
	      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;
8572 8573 8574 8575 8576 8577
      if (i < border)                           // HAVING, ORDER and GROUP BY
      {
        if (extra_funcs.push_back(pos))
          goto err;
      }
      else if (param->copy_funcs.push_back(pos))
unknown's avatar
unknown committed
8578 8579
	goto err;
    }
unknown's avatar
unknown committed
8580 8581
    res_all_fields.push_back(pos);
    ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
8582
      pos;
unknown's avatar
unknown committed
8583
  }
unknown's avatar
unknown committed
8584
  param->copy_field_end= copy;
8585 8586 8587

  for (i= 0; i < border; i++)
    itr++;
unknown's avatar
unknown committed
8588
  itr.sublist(res_selected_fields, elements);
8589 8590 8591 8592 8593 8594
  /*
    Put elements from HAVING, ORDER BY and GROUP BY last to ensure that any
    reference used in these will resolve to a item that is already calculated
  */
  param->copy_funcs.concat(&extra_funcs);

unknown's avatar
unknown committed
8595 8596 8597
  DBUG_RETURN(0);

 err:
8598
  delete [] param->copy_field;			// This is never 0
unknown's avatar
unknown committed
8599
  param->copy_field=0;
8600
err2:
unknown's avatar
unknown committed
8601 8602 8603 8604 8605
  DBUG_RETURN(TRUE);
}


/*
8606 8607 8608 8609
  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
8610 8611 8612 8613 8614 8615
*/

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

8618
  for (; ptr != end; ptr++)
unknown's avatar
unknown committed
8619 8620
    (*ptr->do_copy)(ptr);

unknown's avatar
unknown committed
8621
  List_iterator_fast<Item> it(param->copy_funcs);
unknown's avatar
unknown committed
8622 8623 8624 8625 8626 8627
  Item_copy_string *item;
  while ((item = (Item_copy_string*) it++))
    item->copy();
}


8628 8629
/*
  Make an array of pointers to sum_functions to speed up sum_func calculation
unknown's avatar
unknown committed
8630

8631 8632 8633 8634 8635 8636 8637 8638 8639
  SYNOPSIS
    alloc_func_list()

  RETURN
    0	ok
    1	Error
*/

bool JOIN::alloc_func_list()
unknown's avatar
unknown committed
8640
{
8641 8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667
  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
unknown committed
8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684
/*
  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

  NOTES
    Calls ::setup() for all item_sum objects in field_list

  RETURN
    0  ok
    1  error
*/

8685
bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
8686
			      bool before_group_by)
unknown's avatar
unknown committed
8687
{
8688
  List_iterator_fast<Item> it(field_list);
8689 8690
  Item_sum **func;
  Item *item;
unknown's avatar
unknown committed
8691 8692
  DBUG_ENTER("make_sum_func_list");

8693 8694
  func= sum_funcs;
  while ((item=it++))
unknown's avatar
unknown committed
8695
  {
8696
    if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
unknown's avatar
unknown committed
8697
    {
8698
      *func++= (Item_sum*) item;
unknown's avatar
unknown committed
8699
      /* let COUNT(DISTINCT) create the temporary table */
8700
      if (((Item_sum*) item)->setup(thd))
unknown's avatar
unknown committed
8701 8702 8703
	DBUG_RETURN(TRUE);
    }
  }
8704 8705 8706
  if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
  {
    rollup.state= ROLLUP::STATE_READY;
8707
    if (rollup_make_fields(field_list, send_fields, &func))
8708 8709 8710 8711 8712 8713 8714
      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
8715 8716 8717 8718 8719 8720
  *func=0;					// End marker
  DBUG_RETURN(FALSE);
}


/*
unknown's avatar
unknown committed
8721
  Change all funcs and sum_funcs to fields in tmp table, and create
unknown's avatar
unknown committed
8722 8723 8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734
  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
8735 8736 8737
*/

static bool
8738
change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
unknown's avatar
unknown committed
8739 8740 8741
			 List<Item> &res_selected_fields,
			 List<Item> &res_all_fields,
			 uint elements, List<Item> &all_fields)
unknown's avatar
unknown committed
8742
{
unknown's avatar
unknown committed
8743
  List_iterator_fast<Item> it(all_fields);
unknown's avatar
unknown committed
8744
  Item *item_field,*item;
unknown's avatar
unknown committed
8745 8746
  res_selected_fields.empty();
  res_all_fields.empty();
unknown's avatar
unknown committed
8747

unknown's avatar
unknown committed
8748
  uint i, border= all_fields.elements - elements;
8749
  for (i= 0; (item= it++); i++)
unknown's avatar
unknown committed
8750 8751
  {
    Field *field;
8752
    
unknown's avatar
unknown committed
8753
    if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
8754 8755
      item_field= item;
    else
unknown's avatar
unknown committed
8756
    {
8757
      if (item->type() == Item::FIELD_ITEM)
unknown's avatar
unknown committed
8758
      {
8759
	item_field= item->get_tmp_table_item(thd);
unknown's avatar
unknown committed
8760
      }
8761
      else if ((field= item->get_tmp_table_field()))
8762 8763 8764 8765
      {
	if (item->type() == Item::SUM_FUNC_ITEM && field->table->group)
	  item_field= ((Item_sum*) item)->result_item(field);
	else
unknown's avatar
unknown committed
8766
	  item_field= (Item*) new Item_field(field);
8767 8768 8769 8770 8771 8772 8773
	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];
8774
	  String str(buff,sizeof(buff),&my_charset_bin);
8775 8776 8777 8778
	  str.length(0);
	  item->print(&str);
	  item_field->name= sql_strmake(str.ptr(),str.length());
	}
unknown's avatar
unknown committed
8779
#endif
8780 8781 8782
      }
      else
	item_field= item;
unknown's avatar
unknown committed
8783 8784 8785
    }
    res_all_fields.push_back(item_field);
    ref_pointer_array[((i < border)? all_fields.elements-i-1 : i-border)]=
8786
      item_field;
unknown's avatar
unknown committed
8787
  }
8788

unknown's avatar
unknown committed
8789
  List_iterator_fast<Item> itr(res_all_fields);
8790 8791
  for (i= 0; i < border; i++)
    itr++;
unknown's avatar
unknown committed
8792
  itr.sublist(res_selected_fields, elements);
unknown's avatar
unknown committed
8793 8794 8795 8796 8797
  return FALSE;
}


/*
8798 8799
  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
8800 8801 8802 8803 8804 8805 8806 8807 8808 8809

  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
8810 8811
    0	ok
    1	error
unknown's avatar
unknown committed
8812 8813 8814
*/

static bool
8815
change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
unknown's avatar
unknown committed
8816 8817 8818
			  List<Item> &res_selected_fields,
			  List<Item> &res_all_fields, uint elements,
			  List<Item> &all_fields)
unknown's avatar
unknown committed
8819
{
unknown's avatar
unknown committed
8820
  List_iterator_fast<Item> it(all_fields);
8821
  Item *item, *new_item;
unknown's avatar
unknown committed
8822 8823
  res_selected_fields.empty();
  res_all_fields.empty();
unknown's avatar
unknown committed
8824

unknown's avatar
unknown committed
8825
  uint i, border= all_fields.elements - elements;
8826
  for (i= 0; (item= it++); i++)
unknown's avatar
unknown committed
8827
  {
unknown's avatar
unknown committed
8828 8829
    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)]=
8830
      new_item;
unknown's avatar
unknown committed
8831
  }
8832

unknown's avatar
unknown committed
8833
  List_iterator_fast<Item> itr(res_all_fields);
8834 8835
  for (i= 0; i < border; i++)
    itr++;
unknown's avatar
unknown committed
8836
  itr.sublist(res_selected_fields, elements);
8837

8838
  return thd->is_fatal_error;
unknown's avatar
unknown committed
8839 8840 8841 8842 8843
}



/******************************************************************************
8844
  Code for calculating functions
unknown's avatar
unknown committed
8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863
******************************************************************************/

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
8864
    func->update_field();
unknown's avatar
unknown committed
8865 8866 8867 8868 8869 8870 8871 8872 8873 8874
}


	/* 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
8875
    (void) func->save_in_result_field(1);
unknown's avatar
unknown committed
8876 8877 8878 8879
  return;
}


8880 8881
static bool
init_sum_functions(Item_sum **func_ptr, Item_sum **end_ptr)
unknown's avatar
unknown committed
8882
{
8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894
  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
8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910
}


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
8911
copy_funcs(Item **func_ptr)
unknown's avatar
unknown committed
8912
{
unknown's avatar
unknown committed
8913
  Item *func;
unknown's avatar
unknown committed
8914
  for (; (func = *func_ptr) ; func_ptr++)
unknown's avatar
unknown committed
8915
    func->save_in_result_field(1);
unknown's avatar
unknown committed
8916 8917 8918
}


8919
/*
8920 8921
  Create a condition for a const reference and add this to the
  currenct select for the table
8922
*/
unknown's avatar
unknown committed
8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937

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++)
  {
8938 8939
    Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i].
			      fieldnr-1];
unknown's avatar
unknown committed
8940
    Item *value=join_tab->ref.items[i];
unknown's avatar
unknown committed
8941
    cond->add(new Item_func_equal(new Item_field(field), value));
unknown's avatar
unknown committed
8942
  }
8943
  if (thd->is_fatal_error)
unknown's avatar
unknown committed
8944
    DBUG_RETURN(TRUE);
8945

unknown's avatar
unknown committed
8946 8947
  if (!cond->fixed)
    cond->fix_fields(thd,(TABLE_LIST *) 0, (Item**)&cond);
unknown's avatar
unknown committed
8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958
  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);
}

8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975

/*
  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
8976
/****************************************************************************
8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002
  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
9003
  rollup.item_null= new (thd->mem_root) Item_null();
9004 9005 9006 9007 9008 9009 9010

  /*
    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++)
  {
9011 9012
    List<Item> *rollup_fields= &rollup.fields[i];
    rollup_fields->empty();
9013 9014 9015
    rollup.ref_pointer_arrays[i]= ref_array;
    ref_array+= all_fields.elements;
    for (j=0 ; j < fields_list.elements ; j++)
9016
      rollup_fields->push_back(rollup.item_null);
9017 9018 9019 9020 9021 9022 9023 9024 9025 9026
  }
  return 0;
}
  

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

  SYNOPSIS
    rollup_make_fields()
9027 9028
    fields_arg			List of all fields (hidden and real ones)
    sel_fields			Pointer to selected fields
9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039
    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
*/

9040
bool JOIN::rollup_make_fields(List<Item> &fields_arg, List<Item> &sel_fields,
9041 9042
			      Item_sum ***func)
{
9043 9044
  List_iterator_fast<Item> it(fields_arg);
  Item *first_field= sel_fields.head();
9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067
  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
    ...
  */

9068
  for (level=0 ; level < send_group_parts ; level++)
9069 9070 9071 9072 9073 9074 9075 9076 9077 9078
  {
    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 */
9079
    Item **ref_array= ref_array_start + fields_arg.elements-1;
9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118

    /* 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 */
9119 9120
	ORDER *group_tmp;
	for (group_tmp= start_group ; group_tmp ; group_tmp= group_tmp->next)
9121
	{
9122
	  if (*group_tmp->item == item)
9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188
	  {
	    /*
	      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;
}

9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208
/*
  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();
  }
}
9209

unknown's avatar
unknown committed
9210
/****************************************************************************
9211 9212
  EXPLAIN handling

9213
  Send a description about what how the select will be done to stdout
unknown's avatar
unknown committed
9214 9215
****************************************************************************/

unknown's avatar
unknown committed
9216
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
unknown's avatar
unknown committed
9217
			    bool distinct,const char *message)
unknown's avatar
unknown committed
9218 9219
{
  List<Item> field_list;
9220
  List<Item> item_list;
unknown's avatar
unknown committed
9221
  THD *thd=join->thd;
9222
  select_result *result=join->result;
9223
  Item *item_null= new Item_null();
9224
  CHARSET_INFO *cs= system_charset_info;
unknown's avatar
unknown committed
9225
  DBUG_ENTER("select_describe");
9226
  DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
unknown's avatar
unknown committed
9227
		      (ulong)join->select_lex, join->select_lex->type,
9228
		      message ? message : "NULL"));
9229
  /* Don't log this into the slow query log */
9230
  thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
unknown's avatar
unknown committed
9231
  join->unit->offset_limit_cnt= 0;
9232

unknown's avatar
unknown committed
9233
  if (message)
unknown's avatar
unknown committed
9234
  {
unknown's avatar
unknown committed
9235
    item_list.push_back(new Item_int((int32)
9236
				     join->select_lex->select_number));
unknown's avatar
unknown committed
9237
    item_list.push_back(new Item_string(join->select_lex->type,
unknown's avatar
unknown committed
9238
					strlen(join->select_lex->type), cs));
9239
    for (uint i=0 ; i < 7; i++)
9240
      item_list.push_back(item_null);
unknown's avatar
unknown committed
9241
    item_list.push_back(new Item_string(message,strlen(message),cs));
9242
    if (result->send_data(item_list))
9243
      join->error= 1;
unknown's avatar
unknown committed
9244
  }
9245 9246 9247
  else if (join->select_lex == join->unit->fake_select_lex)
  {
    /* 
unknown's avatar
unknown committed
9248 9249 9250 9251 9252
      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 :)
9253
    */
unknown's avatar
unknown committed
9254
    char table_name_buffer[NAME_LEN];
9255 9256
    item_list.empty();
    /* id */
unknown's avatar
unknown committed
9257
    item_list.push_back(new Item_null);
9258 9259 9260 9261 9262
    /* select_type */
    item_list.push_back(new Item_string(join->select_lex->type,
					strlen(join->select_lex->type),
					cs));
    /* table */
unknown's avatar
unknown committed
9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285
    {
      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 */
9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308
    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
9309 9310 9311 9312
  else
  {
    table_map used_tables=0;
    for (uint i=0 ; i < join->tables ; i++)
unknown's avatar
unknown committed
9313
    {
unknown's avatar
unknown committed
9314 9315
      JOIN_TAB *tab=join->join_tab+i;
      TABLE *table=tab->table;
9316
      char buff[512],*buff_ptr=buff;
9317
      char buff1[512], buff2[512];
unknown's avatar
unknown committed
9318
      char table_name_buffer[NAME_LEN];
unknown's avatar
unknown committed
9319 9320
      String tmp1(buff1,sizeof(buff1),cs);
      String tmp2(buff2,sizeof(buff2),cs);
9321 9322 9323
      tmp1.length(0);
      tmp2.length(0);

unknown's avatar
unknown committed
9324
      item_list.empty();
9325
      /* id */
unknown's avatar
unknown committed
9326
      item_list.push_back(new Item_uint((uint32)
unknown's avatar
unknown committed
9327
				       join->select_lex->select_number));
9328
      /* select_type */
unknown's avatar
unknown committed
9329 9330
      item_list.push_back(new Item_string(join->select_lex->type,
					  strlen(join->select_lex->type),
unknown's avatar
unknown committed
9331
					  cs));
unknown's avatar
unknown committed
9332 9333
      if (tab->type == JT_ALL && tab->select && tab->select->quick)
	tab->type= JT_RANGE;
9334
      /* table */
unknown's avatar
unknown committed
9335
      if (table->derived_select_number)
unknown's avatar
unknown committed
9336
      {
unknown's avatar
unknown committed
9337
	/* Derived table name generation */
9338
	int len= my_snprintf(table_name_buffer, sizeof(table_name_buffer)-1,
unknown's avatar
unknown committed
9339
			     "<derived%u>",
unknown's avatar
unknown committed
9340
			     table->derived_select_number);
9341
	item_list.push_back(new Item_string(table_name_buffer, len, cs));
unknown's avatar
unknown committed
9342 9343 9344 9345
      }
      else
	item_list.push_back(new Item_string(table->table_name,
					    strlen(table->table_name),
unknown's avatar
unknown committed
9346
					    cs));
9347
      /* type */
9348 9349
      item_list.push_back(new Item_string(join_type_str[tab->type],
					  strlen(join_type_str[tab->type]),
unknown's avatar
unknown committed
9350
					  cs));
unknown's avatar
unknown committed
9351
      uint j;
9352
      /* possible_keys */
9353
      if (!tab->keys.is_clear_all())
unknown's avatar
unknown committed
9354
      {
unknown's avatar
unknown committed
9355
        for (j=0 ; j < table->keys ; j++)
9356 9357 9358 9359 9360
        {
          if (tab->keys.is_set(j))
          {
            if (tmp1.length())
              tmp1.append(',');
9361 9362 9363
            tmp1.append(table->key_info[j].name, 
			strlen(table->key_info[j].name),
			system_charset_info);
9364 9365
          }
        }
unknown's avatar
unknown committed
9366
      }
9367
      if (tmp1.length())
unknown's avatar
unknown committed
9368
	item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length(),cs));
unknown's avatar
unknown committed
9369
      else
9370
	item_list.push_back(item_null);
9371
      /* key key_len ref */
unknown's avatar
unknown committed
9372
      if (tab->ref.key_parts)
unknown's avatar
unknown committed
9373
      {
9374 9375
	KEY *key_info=table->key_info+ tab->ref.key;
	item_list.push_back(new Item_string(key_info->name,
9376 9377
					    strlen(key_info->name),
					    system_charset_info));
9378
	item_list.push_back(new Item_int((int32) tab->ref.key_length));
unknown's avatar
unknown committed
9379 9380
	for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
	{
9381 9382
	  if (tmp2.length())
	    tmp2.append(',');
9383 9384
	  tmp2.append((*ref)->name(), strlen((*ref)->name()),
		      system_charset_info);
unknown's avatar
unknown committed
9385
	}
unknown's avatar
unknown committed
9386
	item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length(),cs));
unknown's avatar
unknown committed
9387 9388 9389
      }
      else if (tab->type == JT_NEXT)
      {
9390 9391
	KEY *key_info=table->key_info+ tab->index;
	item_list.push_back(new Item_string(key_info->name,
unknown's avatar
unknown committed
9392
					    strlen(key_info->name),cs));
9393 9394
	item_list.push_back(new Item_int((int32) key_info->key_length));
	item_list.push_back(item_null);
unknown's avatar
unknown committed
9395 9396 9397
      }
      else if (tab->select && tab->select->quick)
      {
9398 9399
	KEY *key_info=table->key_info+ tab->select->quick->index;
	item_list.push_back(new Item_string(key_info->name,
unknown's avatar
unknown committed
9400
					    strlen(key_info->name),cs));
unknown's avatar
unknown committed
9401 9402
	item_list.push_back(new Item_int((int32) tab->select->quick->
					 max_used_key_length));
9403
	item_list.push_back(item_null);
unknown's avatar
unknown committed
9404 9405 9406
      }
      else
      {
9407 9408 9409
	item_list.push_back(item_null);
	item_list.push_back(item_null);
	item_list.push_back(item_null);
unknown's avatar
unknown committed
9410
      }
9411
      /* rows */
9412 9413 9414
      item_list.push_back(new Item_int((longlong) (ulonglong)
				       join->best_positions[i]. records_read,
				       21));
9415
      /* extra */
unknown's avatar
unknown committed
9416
      my_bool key_read=table->key_read;
9417 9418
      if ((tab->type == JT_NEXT || tab->type == JT_CONST) &&
          table->used_keys.is_set(tab->index))
unknown's avatar
unknown committed
9419
	key_read=1;
9420

unknown's avatar
unknown committed
9421
      if (tab->info)
unknown's avatar
unknown committed
9422
	item_list.push_back(new Item_string(tab->info,strlen(tab->info),cs));
9423
      else
unknown's avatar
unknown committed
9424
      {
9425
	if (tab->select)
unknown's avatar
unknown committed
9426
	{
9427 9428
	  if (tab->use_quick == 2)
	  {
9429
            char buf[MAX_KEY/8+1];
unknown's avatar
unknown committed
9430
	    sprintf(buff_ptr,"; Range checked for each record (index map: 0x%s)",
9431
                tab->keys.print(buf));
9432 9433 9434 9435
	    buff_ptr=strend(buff_ptr);
	  }
	  else
	    buff_ptr=strmov(buff_ptr,"; Using where");
unknown's avatar
unknown committed
9436
	}
9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450
	if (key_read)
	  buff_ptr= strmov(buff_ptr,"; Using index");
	if (table->reginfo.not_exists_optimize)
	  buff_ptr= strmov(buff_ptr,"; Not exists");
	if (need_tmp_table)
	{
	  need_tmp_table=0;
	  buff_ptr= strmov(buff_ptr,"; Using temporary");
	}
	if (need_order)
	{
	  need_order=0;
	  buff_ptr= strmov(buff_ptr,"; Using filesort");
	}
9451
	if (distinct & test_all_bits(used_tables,thd->used_tables))
9452 9453
	  buff_ptr= strmov(buff_ptr,"; Distinct");
	if (buff_ptr == buff)
9454 9455
	  buff_ptr+= 2;				// Skip inital "; "
	item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2,
unknown's avatar
unknown committed
9456
					    cs));
unknown's avatar
unknown committed
9457 9458 9459
      }
      // For next iteration
      used_tables|=table->map;
9460
      if (result->send_data(item_list))
9461
	join->error= 1;
unknown's avatar
unknown committed
9462
    }
unknown's avatar
unknown committed
9463
  }
unknown's avatar
unknown committed
9464 9465 9466 9467 9468 9469 9470
  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
9471 9472 9473
  DBUG_VOID_RETURN;
}

9474

unknown's avatar
unknown committed
9475 9476
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
{
unknown's avatar
unknown committed
9477
  DBUG_ENTER("mysql_explain_union");
unknown's avatar
unknown committed
9478 9479
  int res= 0;
  SELECT_LEX *first= unit->first_select();
9480

unknown's avatar
unknown committed
9481 9482 9483 9484
  for (SELECT_LEX *sl= first;
       sl;
       sl= sl->next_select())
  {
9485 9486
    // drop UNCACHEABLE_EXPLAIN, because it is for internal usage only
    uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN);
9487 9488 9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501 9502 9503 9504
    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())
  {
unknown's avatar
unknown committed
9505
    unit->fake_select_lex->select_number= UINT_MAX; // jost for initialization
9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526
    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;
    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
9527
  }
unknown's avatar
unknown committed
9528 9529
  if (res > 0 || thd->net.report_error)
    res= -1; // mysql_explain_select do not report error
unknown's avatar
unknown committed
9530
  DBUG_RETURN(res);
unknown's avatar
unknown committed
9531 9532
}

9533

unknown's avatar
unknown committed
9534 9535 9536 9537 9538
void st_select_lex::print(THD *thd, String *str)
{
  if (!thd)
    thd= current_thd;

9539
  str->append("select ", 7);
unknown's avatar
unknown committed
9540 9541 9542
  
  //options
  if (options & SELECT_STRAIGHT_JOIN)
9543
    str->append("straight_join ", 14);
unknown's avatar
unknown committed
9544
  if ((thd->lex->lock_option == TL_READ_HIGH_PRIORITY) &&
9545
      (this == &thd->lex->select_lex))
9546
    str->append("high_priority ", 14);
unknown's avatar
unknown committed
9547
  if (options & SELECT_DISTINCT)
9548
    str->append("distinct ", 9);
unknown's avatar
unknown committed
9549
  if (options & SELECT_SMALL_RESULT)
unknown's avatar
unknown committed
9550
    str->append("sql_small_result ", 17);
unknown's avatar
unknown committed
9551
  if (options & SELECT_BIG_RESULT)
unknown's avatar
unknown committed
9552
    str->append("sql_big_result ", 15);
unknown's avatar
unknown committed
9553
  if (options & OPTION_BUFFER_RESULT)
unknown's avatar
unknown committed
9554
    str->append("sql_buffer_result ", 18);
unknown's avatar
unknown committed
9555
  if (options & OPTION_FOUND_ROWS)
unknown's avatar
unknown committed
9556
    str->append("sql_calc_found_rows ", 20);
9557
  if (!thd->lex->safe_to_cache_query)
unknown's avatar
unknown committed
9558
    str->append("sql_no_cache ", 13);
unknown's avatar
unknown committed
9559
  if (options & OPTION_TO_QUERY_CACHE)
unknown's avatar
unknown committed
9560
    str->append("sql_cache ", 10);
unknown's avatar
unknown committed
9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580

  //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)
  {
9581
    str->append(" from ", 6);
unknown's avatar
unknown committed
9582 9583 9584 9585 9586 9587 9588 9589 9590 9591 9592 9593 9594 9595 9596 9597 9598
    Item *next_on= 0;
    for (TABLE_LIST *table= (TABLE_LIST *) table_list.first;
	 table;
	 table= table->next)
    {
      if (table->derived)
      {
	str->append('(');
	table->derived->print(str);
	str->append(") ");
	str->append(table->alias);
      }
      else
      {
	str->append(table->db);
	str->append('.');
	str->append(table->real_name);
9599
	if (my_strcasecmp(table_alias_charset, table->real_name, table->alias))
unknown's avatar
unknown committed
9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611
	{
	  str->append(' ');
	  str->append(table->alias);
	}
      }

      if (table->on_expr && ((table->outer_join & JOIN_TYPE_LEFT) ||
			     !(table->outer_join & JOIN_TYPE_RIGHT)))
	next_on= table->on_expr;

      if (next_on)
      {
9612
	str->append(" on(", 4);
unknown's avatar
unknown committed
9613 9614 9615 9616 9617
	next_on->print(str);
	str->append(')');
	next_on= 0;
      }

9618 9619
      TABLE_LIST *next_table;
      if ((next_table= table->next))
unknown's avatar
unknown committed
9620 9621 9622
      {
	if (table->outer_join & JOIN_TYPE_RIGHT)
	{
9623
	  str->append(" right join ", 12);
unknown's avatar
unknown committed
9624 9625 9626 9627
	  if (!(table->outer_join & JOIN_TYPE_LEFT) &&
	      table->on_expr)
	    next_on= table->on_expr;	    
	}
9628
	else if (next_table->straight)
9629
	  str->append(" straight_join ", 15);
9630
	else if (next_table->outer_join & JOIN_TYPE_LEFT)
9631
	  str->append(" left join ", 11);
unknown's avatar
unknown committed
9632
	else
9633
	  str->append(" join ", 6);
unknown's avatar
unknown committed
9634 9635 9636 9637
      }
    }
  }

9638 9639
  // Where
  Item *cur_where= where;
unknown's avatar
unknown committed
9640
  if (join)
9641 9642
    cur_where= join->conds;
  if (cur_where)
unknown's avatar
unknown committed
9643
  {
9644
    str->append(" where ", 7);
9645
    cur_where->print(str);
unknown's avatar
unknown committed
9646 9647
  }

9648
  // group by & olap
unknown's avatar
unknown committed
9649 9650
  if (group_list.elements)
  {
9651
    str->append(" group by ", 10);
unknown's avatar
unknown committed
9652 9653 9654 9655
    print_order(str, (ORDER *) group_list.first);
    switch (olap)
    {
      case CUBE_TYPE:
9656
	str->append(" with cube", 10);
unknown's avatar
unknown committed
9657 9658
	break;
      case ROLLUP_TYPE:
9659
	str->append(" with rollup", 12);
unknown's avatar
unknown committed
9660 9661 9662 9663 9664 9665
	break;
      default:
	;  //satisfy compiler
    }
  }

9666 9667
  // having
  Item *cur_having= having;
unknown's avatar
unknown committed
9668
  if (join)
9669
    cur_having= join->having;
unknown's avatar
unknown committed
9670

9671
  if (cur_having)
unknown's avatar
unknown committed
9672
  {
9673
    str->append(" having ", 8);
9674
    cur_having->print(str);
unknown's avatar
unknown committed
9675 9676 9677 9678
  }

  if (order_list.elements)
  {
9679
    str->append(" order by ", 10);
unknown's avatar
unknown committed
9680 9681 9682 9683 9684 9685 9686 9687
    print_order(str, (ORDER *) order_list.first);
  }

  // limit
  print_limit(thd, str);

  // PROCEDURE unsupported here
}
9688 9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703 9704 9705 9706 9707 9708 9709 9710 9711


/*
  change select_result object of JOIN

  SYNOPSIS
    JOIN::change_result()
    res		new select_result object

  RETURN
    0 - OK
    -1 - error
*/

int JOIN::change_result(select_result *res)
{
  DBUG_ENTER("JOIN::change_result");
  result= res;
  if (!procedure && result->prepare(fields_list, select_lex->master_unit()))
  {
    DBUG_RETURN(-1);
  }
  DBUG_RETURN(0);
}