sql_select.cc 209 KB
Newer Older
1
/* Copyright (C) 2000-2003 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

27
#include "opt_ft.h"
unknown's avatar
unknown committed
28

unknown's avatar
unknown committed
29 30 31 32 33 34
#include <m_ctype.h>
#include <hash.h>
#include <ft_global.h>
#include <assert.h>

const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
35
			      "MAYBE_REF","ALL","range","index","fulltext" };
unknown's avatar
unknown committed
36 37

static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
unknown's avatar
unknown committed
38
				 DYNAMIC_ARRAY *keyuse);
39 40
static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
				JOIN_TAB *join_tab,
41
                                uint tables,COND *conds,table_map table_map);
unknown's avatar
unknown committed
42 43
static int sort_keyuse(KEYUSE *a,KEYUSE *b);
static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key);
44 45
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
			       table_map used_tables);
unknown's avatar
unknown committed
46 47 48 49 50 51
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
52 53
static store_key *get_store_key(THD *thd,
				KEYUSE *keyuse, table_map used_tables,
unknown's avatar
unknown committed
54 55 56 57 58 59 60 61 62 63 64
				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);
static void join_free(JOIN *join);
static bool only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables);
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);
65
static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
unknown's avatar
unknown committed
66 67 68 69 70 71 72 73
			    List<Item> &fields, bool send_row,
			    uint select_options, const char *info,
			    Item *having, Procedure *proc);
static COND *optimize_cond(COND *conds,Item::cond_result *cond_value);
static COND *remove_eq_conds(COND *cond,Item::cond_result *cond_value);
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,
74
				    ulong options);
unknown's avatar
unknown committed
75 76 77 78 79 80 81 82 83 84 85 86 87 88
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);
static int flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last);
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);
89
static int join_read_const_table(JOIN_TAB *tab, POSITION *pos);
unknown's avatar
unknown committed
90 91 92 93
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);
94
static int join_read_last_key(JOIN_TAB *tab);
unknown's avatar
unknown committed
95 96 97 98 99
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);
100 101 102 103 104 105
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
106 107 108 109 110 111 112
static int join_ft_read_first(JOIN_TAB *tab);
static int join_ft_read_next(READ_RECORD *info);
static COND *make_cond_for_table(COND *cond,table_map table,
				 table_map used_table);
static Item* part_of_refkey(TABLE *form,Field *field);
static uint find_shortest_key(TABLE *table, key_map usable_keys);
static bool test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,
113
				    ha_rows select_limit, bool no_changes);
unknown's avatar
unknown committed
114 115
static int create_sort_index(JOIN_TAB *tab,ORDER *order,ha_rows filesort_limit,
			     ha_rows select_limit);
116 117
static int remove_duplicates(JOIN *join,TABLE *entry,List<Item> &fields,
			     Item *having);
unknown's avatar
unknown committed
118
static int remove_dup_with_compare(THD *thd, TABLE *entry, Field **field,
119
				   ulong offset,Item *having);
unknown's avatar
unknown committed
120 121
static int remove_dup_with_hash_index(THD *thd, TABLE *table,
				      uint field_count, Field **first_field,
122
				      ulong key_length,Item *having);
unknown's avatar
unknown committed
123 124 125 126 127 128 129 130 131 132
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);
static void reset_cache(JOIN_CACHE *cache);
static void read_cached_record(JOIN_TAB *tab);
static bool cmp_buffer_with_ref(JOIN_TAB *tab);
static int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
		       List<Item> &all_fields, ORDER *order, bool *hidden);
static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
			     List<Item> &all_fields,ORDER *new_order);
133 134 135
static ORDER *create_distinct_group(THD *thd, ORDER *order,
				    List<Item> &fields,
				    bool *all_order_by_fields_used);
unknown's avatar
unknown committed
136 137 138 139 140
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);
static bool alloc_group_fields(JOIN *join,ORDER *group);
static bool make_sum_func_list(JOIN *join,List<Item> &fields);
141
static bool change_to_use_tmp_fields(List<Item> &func);
unknown's avatar
unknown committed
142 143 144 145 146 147 148
static bool change_refs_to_tmp_fields(THD *thd, List<Item> &func);
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);
static void init_sum_functions(Item_sum **func);
static bool update_sum_func(Item_sum **func);
unknown's avatar
unknown committed
149
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
unknown's avatar
unknown committed
150
			    bool distinct, const char *message=NullS);
151
static void describe_info(JOIN *join, const char *info);
152

153 154 155 156 157 158 159 160
/*
  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;
161 162

#ifdef DISABLED_UNTIL_REWRITTEN_IN_4_1
163 164
  if (lex->olap)
  {
165 166 167
    SELECT_LEX *sl, *sl_next;
    int error;
    for (sl= &select_lex; sl; sl=sl_next)
168
    {
169 170
      sl_next=sl->next;				// Save if sl->next changes
      if (sl->olap != UNSPECIFIED_OLAP_TYPE)
171
      {
172
	if ((error=handle_olaps(lex,sl)))
unknown's avatar
unknown committed
173
	  return error;
174
	lex->last_selects->next=sl_next;
175 176 177 178
      }
    }
    lex->select = select_lex;
  }
unknown's avatar
unknown committed
179
#endif /* DISABLED_UNTIL_REWRITTEN_IN_4_1 */
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
  if (select_lex->next)
    res=mysql_union(thd,lex,result);
  else
    res=mysql_select(thd,(TABLE_LIST*) select_lex->table_list.first,
		     select_lex->item_list,
		     select_lex->where,
		     (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,
		     result);
  if (res && result)
    result->abort();
  delete result;
unknown's avatar
unknown committed
195
  return res;
196 197 198
}


unknown's avatar
unknown committed
199
/*****************************************************************************
200 201
  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
202 203 204 205 206
*****************************************************************************/

int
mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
	     ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
unknown's avatar
unknown committed
207
	     ulong select_options,select_result *result)
unknown's avatar
unknown committed
208 209
{
  TABLE		*tmp_table;
unknown's avatar
unknown committed
210
  int		error, tmp_error;
unknown's avatar
unknown committed
211
  bool		need_tmp,hidden_group_fields;
212
  bool		simple_order,simple_group,no_order, skip_sort_order;
unknown's avatar
unknown committed
213
  ha_rows	select_limit;
unknown's avatar
unknown committed
214 215 216 217 218 219 220
  Item::cond_result cond_value;
  SQL_SELECT	*select;
  DYNAMIC_ARRAY keyuse;
  JOIN		join;
  Procedure	*procedure;
  List<Item>	all_fields(fields);
  bool		select_distinct;
221
  SELECT_LEX *cur_sel = thd->lex.select;
unknown's avatar
unknown committed
222 223 224 225 226 227 228
  DBUG_ENTER("mysql_select");

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

  select_distinct=test(select_options & SELECT_DISTINCT);
  tmp_table=0;
  select=0;
229
  no_order=skip_sort_order=0;
unknown's avatar
unknown committed
230 231
  bzero((char*) &keyuse,sizeof(keyuse));
  thd->proc_info="init";
unknown's avatar
unknown committed
232
  thd->used_tables=0;				// Updated by setup_fields
233 234 235 236
  /* select_limit is used to decide if we are likely to scan the whole table */
  select_limit= thd->select_limit;
  if (having || (select_options & OPTION_FOUND_ROWS))
    select_limit= HA_POS_ERROR;
unknown's avatar
unknown committed
237

238
  if (setup_tables(tables) ||
unknown's avatar
unknown committed
239
      setup_fields(thd,tables,fields,1,&all_fields,1) ||
unknown's avatar
unknown committed
240 241
      setup_conds(thd,tables,&conds) ||
      setup_order(thd,tables,fields,all_fields,order) ||
unknown's avatar
unknown committed
242
      setup_group(thd,tables,fields,all_fields,group,&hidden_group_fields))
unknown's avatar
unknown committed
243 244 245 246 247 248 249 250 251 252 253
    DBUG_RETURN(-1);				/* purecov: inspected */

  if (having)
  {
    thd->where="having clause";
    thd->allow_sum_func=1;
    if (having->fix_fields(thd,tables) || thd->fatal_error)
      DBUG_RETURN(-1);				/* purecov: inspected */
    if (having->with_sum_func)
      having->split_sum_func(all_fields);
  }
254
  if (setup_ftfuncs(thd)) /* should be after having->fix_fields */
unknown's avatar
unknown committed
255
    DBUG_RETURN(-1);
unknown's avatar
unknown committed
256 257 258 259 260
  /*
    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;
261
  */
unknown's avatar
unknown committed
262 263 264 265 266 267
  join.table=0;
  join.tables=0;
  {
    if (!group)
    {
      uint flag=0;
unknown's avatar
unknown committed
268
      List_iterator_fast<Item> it(fields);
unknown's avatar
unknown committed
269 270 271 272 273
      Item *item;
      while ((item= it++))
      {
	if (item->with_sum_func)
	  flag|=1;
unknown's avatar
unknown committed
274
	else if (!(flag & 2) && !item->const_item())
unknown's avatar
unknown committed
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
	  flag|=2;
      }
      if (flag == 3)
      {
	my_error(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,MYF(0));
	DBUG_RETURN(-1);
      }
    }
    TABLE_LIST *table;
    for (table=tables ; table ; table=table->next)
      join.tables++;
  }
  procedure=setup_procedure(thd,proc_param,result,fields,&error);
  if (error)
    DBUG_RETURN(-1);				/* purecov: inspected */
  if (procedure)
  {
    if (setup_new_fields(thd,tables,fields,all_fields,procedure->param_fields))
    {						/* purecov: inspected */
      delete procedure;				/* purecov: inspected */
      DBUG_RETURN(-1);				/* purecov: inspected */
    }
    if (procedure->group)
    {
      if (!test_if_subpart(procedure->group,group))
      {						/* purecov: inspected */
	my_message(0,"Can't handle procedures with differents groups yet",
		   MYF(0));			/* purecov: inspected */
	delete procedure;			/* purecov: inspected */
	DBUG_RETURN(-1);			/* purecov: inspected */
      }
    }
#ifdef NOT_NEEDED
    else if (!group && procedure->flags & PROC_GROUP)
    {
      my_message(0,"Select must have a group with this procedure",MYF(0));
      delete procedure;
      DBUG_RETURN(-1);
    }
#endif
    if (order && (procedure->flags & PROC_NO_SORT))
    { /* purecov: inspected */
      my_message(0,"Can't use order with this procedure",MYF(0)); /* purecov: inspected */
      delete procedure; /* purecov: inspected */
      DBUG_RETURN(-1); /* purecov: inspected */
    }
  }

  /* Init join struct */
  join.thd=thd;
  join.lock=thd->lock;
  join.join_tab=0;
  join.tmp_table_param.copy_field=0;
  join.sum_funcs=0;
329
  join.send_records=join.found_records=join.examined_rows=0;
unknown's avatar
unknown committed
330 331 332 333
  join.tmp_table_param.end_write_records= HA_POS_ERROR;
  join.first_record=join.sort_and_group=0;
  join.select_options=select_options;
  join.result=result;
unknown's avatar
unknown committed
334
  count_field_types(&join.tmp_table_param,all_fields,0);
unknown's avatar
unknown committed
335 336
  join.const_tables=0;
  join.having=0;
337
  join.do_send_rows = 1;
unknown's avatar
unknown committed
338
  join.group= group != 0;
unknown's avatar
unknown committed
339 340
  join.row_limit= ((select_distinct || order || group) ? HA_POS_ERROR :
		   thd->select_limit);
unknown's avatar
unknown committed
341 342 343 344

#ifdef RESTRICTED_GROUP
  if (join.sum_func_count && !group && (join.func_count || join.field_count))
  {
unknown's avatar
unknown committed
345
    my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0));
unknown's avatar
unknown committed
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
    delete procedure;
    DBUG_RETURN(-1);
  }
#endif
  if (!procedure && result->prepare(fields))
  {						/* purecov: inspected */
    DBUG_RETURN(-1);				/* purecov: inspected */
  }

#ifdef HAVE_REF_TO_FIELDS			// Not done yet
  /* Add HAVING to WHERE if possible */
  if (having && !group && ! join.sum_func_count)
  {
    if (!conds)
    {
      conds=having;
      having=0;
    }
    else if ((conds=new Item_cond_and(conds,having)))
    {
      conds->fix_fields(thd,tables);
      conds->change_ref_to_fields(thd,tables);
368
      conds->top_level_item();
unknown's avatar
unknown committed
369 370 371 372 373 374 375 376 377 378 379 380 381
      having=0;
    }
  }
#endif

  conds=optimize_cond(conds,&cond_value);
  if (thd->fatal_error)				// Out of memory
  {
    delete procedure;
    DBUG_RETURN(0);
  }
  if (cond_value == Item::COND_FALSE || !thd->select_limit)
  {					/* Impossible cond */
382 383 384 385
    error=return_zero_rows(&join, result, tables, fields,
			   join.tmp_table_param.sum_func_count != 0 && !group,
			   select_options,"Impossible WHERE",having,
			   procedure);
unknown's avatar
unknown committed
386 387 388 389 390 391 392 393
    delete procedure;
    DBUG_RETURN(error);
  }

  /* Optimize count(*), min() and max() */
  if (tables && join.tmp_table_param.sum_func_count && ! group)
  {
    int res;
unknown's avatar
unknown committed
394 395 396 397
    /*
    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
398 399
    if ((res=opt_sum_query(tables, all_fields, conds)))
    {
unknown's avatar
unknown committed
400 401 402 403 404
      if (res > 1)
      {
	delete procedure;
	DBUG_RETURN(-1);
      }
unknown's avatar
unknown committed
405 406
      if (res < 0)
      {
407 408 409
	error=return_zero_rows(&join, result, tables, fields, !group,
			       select_options,"No matching min/max row",
			       having,procedure);
unknown's avatar
unknown committed
410 411 412 413 414
	delete procedure;
	DBUG_RETURN(error);
      }
      if (select_options & SELECT_DESCRIBE)
      {
415
	describe_info(&join, "Select tables optimized away");
unknown's avatar
unknown committed
416
	delete procedure;
unknown's avatar
unknown committed
417
	DBUG_RETURN(error);
unknown's avatar
unknown committed
418 419 420 421 422 423 424 425
      }
      tables=0;					// All tables resolved
    }
  }
  if (!tables)
  {						// Only test of functions
    error=0;
    if (select_options & SELECT_DESCRIBE)
426
      describe_info(&join, "No tables used");
unknown's avatar
unknown committed
427 428 429 430 431
    else
    {
      result->send_fields(fields,1);
      if (!having || having->val_int())
      {
432
	if (join.do_send_rows && result->send_data(fields))
unknown's avatar
unknown committed
433 434 435 436 437 438 439 440 441 442 443
	{
	  result->send_error(0,NullS);		/* purecov: inspected */
	  error=1;
	}
	else
	  error=(int) result->send_eof();
      }
      else
	error=(int) result->send_eof();
    }
    delete procedure;
unknown's avatar
unknown committed
444
    DBUG_RETURN(error);
unknown's avatar
unknown committed
445 446 447 448 449 450 451
  }

  error = -1;
  join.sort_by_table=get_sort_by_table(order,group,tables);

  /* Calculate how to do the join */
  thd->proc_info="statistics";
452
  if (make_join_statistics(&join,tables,conds,&keyuse) || thd->fatal_error)
unknown's avatar
unknown committed
453
    goto err;
454

unknown's avatar
unknown committed
455
  thd->proc_info="preparing";
unknown's avatar
unknown committed
456 457 458

  select_distinct= select_distinct && (join.const_tables != join.tables);

unknown's avatar
unknown committed
459 460
  if (result->initialize_tables(&join))
    goto err;
461 462
  if (join.const_table_map != join.found_const_table_map &&
      !(select_options & SELECT_DESCRIBE))
unknown's avatar
unknown committed
463
  {
464
    error=return_zero_rows(&join,result,tables,fields,
unknown's avatar
unknown committed
465
			   join.tmp_table_param.sum_func_count != 0 &&
466 467
			   !group,0,"no matching row in const table",having,
			   procedure);
unknown's avatar
unknown committed
468 469 470
    goto err;
  }
  if (!(thd->options & OPTION_BIG_SELECTS) &&
unknown's avatar
unknown committed
471
      join.best_read > (double) thd->variables.max_join_size &&
unknown's avatar
unknown committed
472 473 474 475 476 477
      !(select_options & SELECT_DESCRIBE))
  {						/* purecov: inspected */
    result->send_error(ER_TOO_BIG_SELECT,ER(ER_TOO_BIG_SELECT)); /* purecov: inspected */
    error= 1;					/* purecov: inspected */
    goto err;					/* purecov: inspected */
  }
unknown's avatar
unknown committed
478 479
  if (join.const_tables && !thd->locked_tables &&
      !(select_options & SELECT_NO_UNLOCK))
480 481 482 483 484 485 486 487 488 489 490 491 492 493
  {
    TABLE **table, **end;
    for (table=join.table, end=table + join.const_tables ;
	 table != end;
	 table++)
    {
      /* BDB tables require that we call index_end() before doing an unlock */
      if ((*table)->key_read)
      {
	(*table)->key_read=0;
	(*table)->file->extra(HA_EXTRA_NO_KEYREAD);
      }
      (*table)->file->index_end();
    }
unknown's avatar
unknown committed
494
    mysql_unlock_some_tables(thd, join.table,join.const_tables);
495
  }
496 497 498 499 500
  if (!conds && join.outer_join)
  {
    /* Handle the case where we have an OUTER JOIN without a WHERE */
    conds=new Item_int((longlong) 1,1);	// Always true
  }
unknown's avatar
unknown committed
501 502 503 504 505 506 507 508 509
  select=make_select(*join.table, join.const_table_map,
		     join.const_table_map,conds,&error);
  if (error)
  { /* purecov: inspected */
    error= -1; /* purecov: inspected */
    goto err; /* purecov: inspected */
  }
  if (make_join_select(&join,select,conds))
  {
510 511 512 513 514
    error=return_zero_rows(&join, result, tables, fields,
			   join.tmp_table_param.sum_func_count != 0 && !group,
			   select_options,
			   "Impossible WHERE noticed after reading const tables",
			   having,procedure);
unknown's avatar
unknown committed
515 516 517 518 519 520
    goto err;
  }

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

  /* Optimize distinct away if possible */
unknown's avatar
unknown committed
521 522 523 524 525 526 527 528 529 530
  {
    ORDER *org_order= order;
    order=remove_const(&join,order,conds,&simple_order);
    /*
      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;
  }
unknown's avatar
unknown committed
531 532 533 534 535
  if (group || join.tmp_table_param.sum_func_count)
  {
    if (! hidden_group_fields)
      select_distinct=0;
  }
536
  else if (select_distinct && join.tables - join.const_tables == 1)
unknown's avatar
unknown committed
537
  {
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
    /*
      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.
    */
    JOIN_TAB *tab= &join.join_tab[join.const_tables];
    bool all_order_fields_used;
    if (order)
      skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1);
    if ((group=create_distinct_group(thd, order, fields,
				     &all_order_fields_used)))
    {
      bool skip_group= (skip_sort_order &&
			test_if_skip_sort_order(tab, group, select_limit,
						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)
571 572 573 574 575 576 577 578 579
	{
	  if (order && skip_sort_order)
	  {
	    /*
	      Force MySQL to read the table in sorted order to get result in
	      ORDER BY order.
	    */	    
	    join.tmp_table_param.quick_group=0;
	  }
580
	  order=0;
581
	}
582 583 584 585 586
	join.group=1;				// For end_write_group
      }
      else
	group= 0;
    } else if (thd->fatal_error)			// End of memory
unknown's avatar
unknown committed
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
      goto err;
  }
  group=remove_const(&join,group,conds,&simple_group);
  if (!group && join.group)
  {
    order=0;					// The output has only one row
    simple_order=1;
  }

  calc_group_buffer(&join,group);
  join.send_group_parts=join.tmp_table_param.group_parts; /* Save org parts */
  if (procedure && procedure->group)
  {
    group=procedure->group=remove_const(&join,procedure->group,conds,
					&simple_group);
    calc_group_buffer(&join,group);
  }

  if (test_if_subpart(group,order) ||
      (!group && join.tmp_table_param.sum_func_count))
    order=0;

unknown's avatar
unknown committed
609
  // Can't use sort on head table if using row cache
unknown's avatar
unknown committed
610 611 612 613 614 615 616 617
  if (join.full_join)
  {
    if (group)
      simple_group=0;
    if (order)
      simple_order=0;
  }

618 619 620 621 622 623 624 625 626
  /*
    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.
  */
unknown's avatar
unknown committed
627 628
  need_tmp= (join.const_tables != join.tables &&
	     ((select_distinct || !simple_order || !simple_group) ||
629 630
	      (group && order) || 
	      test(select_options & OPTION_BUFFER_RESULT)));
unknown's avatar
unknown committed
631

unknown's avatar
unknown committed
632 633 634
  // No cache for MATCH
  make_join_readinfo(&join,
		     (select_options & (SELECT_DESCRIBE |
635
					SELECT_NO_JOIN_CACHE)) |
636 637 638 639 640 641 642 643 644
		     (cur_sel->ftfunc_list.elements ? SELECT_NO_JOIN_CACHE :
		      0));
  /*
    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
645 646 647 648 649 650

#ifdef HAVE_INNOBASE_DB
  if (need_tmp || select_distinct || group || order)
  {
    for (uint i_h = join.const_tables; i_h < join.tables; i_h++)
    {
651
      TABLE*	  table_h = join.join_tab[i_h].table;
652
      if (table_h->db_type == DB_TYPE_INNODB)
653
	table_h->file->extra(HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE);
unknown's avatar
unknown committed
654 655 656 657
    }
  }
#endif

unknown's avatar
unknown committed
658 659 660 661 662 663 664 665
  DBUG_EXECUTE("info",TEST_join(&join););
  /*
    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.
    */
  if ((order || group) && join.join_tab[join.const_tables].type != JT_ALL &&
666
      join.join_tab[join.const_tables].type != JT_FT &&
unknown's avatar
unknown committed
667 668 669 670 671 672 673 674
      (order && simple_order || group && simple_group))
  {
    if (add_ref_to_table_cond(thd,&join.join_tab[join.const_tables]))
      goto err;
  }

  if (!(select_options & SELECT_BIG_RESULT) &&
      ((group && join.const_tables != join.tables &&
675 676
	(!simple_group ||
	 !test_if_skip_sort_order(&join.join_tab[join.const_tables], group,
unknown's avatar
merge  
unknown committed
677
				  thd->select_limit,0))) ||
unknown's avatar
unknown committed
678 679 680 681 682 683 684 685 686 687 688 689
       select_distinct) &&
      join.tmp_table_param.quick_group && !procedure)
  {
    need_tmp=1; simple_order=simple_group=0;	// Force tmp table without sort
  }

  if (select_options & SELECT_DESCRIBE)
  {
    if (!order && !no_order)
      order=group;
    if (order &&
	(join.const_tables == join.tables ||
690
	 ((simple_order || skip_sort_order) &&
691
	  test_if_skip_sort_order(&join.join_tab[join.const_tables], order,
692
				  select_limit, 0))))
unknown's avatar
unknown committed
693 694
      order=0;
    select_describe(&join,need_tmp,
695
		    order != 0 && !skip_sort_order,
unknown's avatar
unknown committed
696
		    select_distinct);
unknown's avatar
unknown committed
697 698 699 700
    error=0;
    goto err;
  }

701
  /* Perform FULLTEXT search before all regular searches */
702
  init_ftfuncs(thd,test(order));
703

unknown's avatar
unknown committed
704 705 706 707 708 709
  /* 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";

710 711
    join.tmp_table_param.hidden_field_count= (all_fields.elements -
					      fields.elements);
unknown's avatar
unknown committed
712 713 714 715 716 717 718
    if (!(tmp_table =
	  create_tmp_table(thd,&join.tmp_table_param,all_fields,
			   ((!simple_group && !procedure &&
			     !(test_flags & TEST_NO_KEY_GROUP)) ?
			    group : (ORDER*) 0),
			   group ? 0 : select_distinct,
			   group && simple_group,
719
			   (order == 0 || skip_sort_order) &&
720
			   select_limit != HA_POS_ERROR,
unknown's avatar
unknown committed
721 722 723 724 725 726 727 728 729 730 731 732
			   join.select_options)))
      goto err;					/* purecov: inspected */

    if (having && (join.sort_and_group || (tmp_table->distinct && !group)))
      join.having=having;

    /* if group or order on first table, sort first */
    if (group && simple_group)
    {
      DBUG_PRINT("info",("Sorting for group"));
      thd->proc_info="Sorting for group";
      if (create_sort_index(&join.join_tab[join.const_tables],group,
unknown's avatar
unknown committed
733
			    HA_POS_ERROR, HA_POS_ERROR) ||
unknown's avatar
unknown committed
734 735 736 737 738 739 740 741 742 743 744 745 746 747
	  make_sum_func_list(&join,all_fields) ||
	  alloc_group_fields(&join,group))
	goto err;
      group=0;
    }
    else
    {
      if (make_sum_func_list(&join,all_fields))
	goto err;
      if (!group && ! tmp_table->distinct && order && simple_order)
      {
	DBUG_PRINT("info",("Sorting for order"));
	thd->proc_info="Sorting for order";
	if (create_sort_index(&join.join_tab[join.const_tables],order,
unknown's avatar
unknown committed
748
			      HA_POS_ERROR, HA_POS_ERROR))
unknown's avatar
unknown committed
749 750 751 752
	  goto err;				/* purecov: inspected */
	order=0;
      }
    }
unknown's avatar
unknown committed
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769

    /*
      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 (tmp_table->distinct)
    {
      table_map used_tables= thd->used_tables;
      JOIN_TAB *join_tab=join.join_tab+join.tables-1;
      do
      {
	if (used_tables & join_tab->table->map)
	  break;
	join_tab->not_used_in_distinct=1;
      } while (join_tab-- != join.join_tab);
770 771 772
      /* Optimize "select distinct b from t1 order by key_part_1 limit #" */
      if (order && skip_sort_order)
      {
773 774 775 776
	/* Should always succeed */
	if (test_if_skip_sort_order(&join.join_tab[join.const_tables],
				    order, thd->select_limit,0))
	  order=0;
777
      }
unknown's avatar
unknown committed
778 779 780
    }

    /* Copy data to the temporary table */
unknown's avatar
unknown committed
781
    thd->proc_info="Copying to tmp table";
782 783 784
    if ((tmp_error=do_select(&join,(List<Item> *) 0,tmp_table,0)))
    {
      error=tmp_error;
unknown's avatar
unknown committed
785
      goto err;					/* purecov: inspected */
786
    }
unknown's avatar
unknown committed
787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
    if (join.having)
      join.having=having=0;			// Allready done

    /* Change sum_fields reference to calculated fields in tmp_table */
    if (join.sort_and_group || tmp_table->group)
    {
      if (change_to_use_tmp_fields(all_fields))
	goto err;
      join.tmp_table_param.field_count+=join.tmp_table_param.sum_func_count+
	join.tmp_table_param.func_count;
      join.tmp_table_param.sum_func_count=join.tmp_table_param.func_count=0;
    }
    else
    {
      if (change_refs_to_tmp_fields(thd,all_fields))
	goto err;
      join.tmp_table_param.field_count+=join.tmp_table_param.func_count;
      join.tmp_table_param.func_count=0;
    }
    if (procedure)
      procedure->update_refs();
    if (tmp_table->group)
    {						// Already grouped
unknown's avatar
unknown committed
810
      if (!order && !no_order && !skip_sort_order)
unknown's avatar
unknown committed
811 812 813 814 815
	order=group;				/* order by group */
      group=0;
    }

    /*
816 817 818 819 820
      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
821 822
    */

unknown's avatar
unknown committed
823 824 825
    if (group && (!test_if_subpart(group,order) || select_distinct) ||
	(select_distinct &&
	 join.tmp_table_param.using_indirect_summary_function))
unknown's avatar
unknown committed
826 827 828 829 830 831 832 833 834
    {					/* Must copy to another table */
      TABLE *tmp_table2;
      DBUG_PRINT("info",("Creating group table"));

      /* Free first data from old join */
      join_free(&join);
      if (make_simple_join(&join,tmp_table))
	goto err;
      calc_group_buffer(&join,group);
unknown's avatar
unknown committed
835 836 837 838
      count_field_types(&join.tmp_table_param,all_fields,
			select_distinct && !group);
      join.tmp_table_param.hidden_field_count=(all_fields.elements-
					       fields.elements);
unknown's avatar
unknown committed
839 840 841

      /* group data to new table */
      if (!(tmp_table2 = create_tmp_table(thd,&join.tmp_table_param,all_fields,
unknown's avatar
unknown committed
842 843 844
					  (ORDER*) 0,
					  select_distinct && !group,
					  1, 0,
unknown's avatar
unknown committed
845 846 847 848 849
					  join.select_options)))
	goto err;				/* purecov: inspected */
      if (group)
      {
	thd->proc_info="Creating sort index";
unknown's avatar
unknown committed
850
	if (create_sort_index(join.join_tab,group,HA_POS_ERROR, HA_POS_ERROR) ||
unknown's avatar
unknown committed
851 852
	    alloc_group_fields(&join,group))
	{
unknown's avatar
unknown committed
853
	  free_tmp_table(thd,tmp_table2);	/* purecov: inspected */
unknown's avatar
unknown committed
854 855 856 857 858
	  goto err;				/* purecov: inspected */
	}
	group=0;
      }
      thd->proc_info="Copying to group table";
859
      tmp_error= -1;
unknown's avatar
unknown committed
860
      if (make_sum_func_list(&join,all_fields) ||
861
	  (tmp_error=do_select(&join,(List<Item> *) 0,tmp_table2,0)))
unknown's avatar
unknown committed
862
      {
863
	error=tmp_error;
unknown's avatar
unknown committed
864 865 866 867 868 869 870 871 872
	free_tmp_table(thd,tmp_table2);
	goto err;				/* purecov: inspected */
      }
      end_read_record(&join.join_tab->read_record);
      free_tmp_table(thd,tmp_table);
      join.const_tables=join.tables;		// Mark free for join_free()
      tmp_table=tmp_table2;
      join.join_tab[0].table=0;			// Table is freed

873
      if (change_to_use_tmp_fields(all_fields)) // No sum funcs anymore
unknown's avatar
unknown committed
874 875 876 877 878 879
	goto err;
      join.tmp_table_param.field_count+=join.tmp_table_param.sum_func_count;
      join.tmp_table_param.sum_func_count=0;
    }

    if (tmp_table->distinct)
880
      select_distinct=0;			/* Each row is unique */
unknown's avatar
unknown committed
881 882 883 884 885

    join_free(&join);				/* Free quick selects */
    if (select_distinct && ! group)
    {
      thd->proc_info="Removing duplicates";
886 887 888 889 890
      if (having)
	having->update_used_tables();
      if (remove_duplicates(&join,tmp_table,fields, having))
	goto err;				/* purecov: inspected */
      having=0;
unknown's avatar
unknown committed
891 892 893 894 895 896
      select_distinct=0;
    }
    tmp_table->reginfo.lock_type=TL_UNLOCK;
    if (make_simple_join(&join,tmp_table))
      goto err;
    calc_group_buffer(&join,group);
unknown's avatar
unknown committed
897
    count_field_types(&join.tmp_table_param,all_fields,0);
unknown's avatar
unknown committed
898 899 900 901 902 903
  }
  if (procedure)
  {
    if (procedure->change_columns(fields) ||
	result->prepare(fields))
      goto err;
unknown's avatar
unknown committed
904
    count_field_types(&join.tmp_table_param,all_fields,0);
unknown's avatar
unknown committed
905 906 907 908 909
  }
  if (join.group || join.tmp_table_param.sum_func_count ||
      (procedure && (procedure->flags & PROC_GROUP)))
  {
    alloc_group_fields(&join,group);
unknown's avatar
unknown committed
910
    setup_copy_fields(thd, &join.tmp_table_param,all_fields);
unknown's avatar
unknown committed
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937
    if (make_sum_func_list(&join,all_fields) || thd->fatal_error)
      goto err; /* purecov: inspected */
  }
  if (group || order)
  {
    DBUG_PRINT("info",("Sorting for send_fields"));
    thd->proc_info="Sorting result";
    /* If we have already done the group, add HAVING to sorted table */
    if (having && ! group && ! join.sort_and_group)
    {
      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;

      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))
	    goto err;
	if (!table->select->cond)
	  table->select->cond=sort_table_cond;
	else					// This should never happen
	  if (!(table->select->cond=new Item_cond_and(table->select->cond,
						      sort_table_cond)))
	    goto err;
	table->select_cond=table->select->cond;
938
	table->select_cond->top_level_item();
unknown's avatar
unknown committed
939 940 941 942 943 944
	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(conds,"having after sort"););
      }
    }
945
    if (group)
unknown's avatar
unknown committed
946 947 948 949 950 951 952 953 954 955 956
      select_limit= HA_POS_ERROR;
    else
    {
      /*
	We can abort sorting after thd->select_limit rows if we there is no
	WHERE clause for any tables after the sorted one.
      */
      JOIN_TAB *table= &join.join_tab[join.const_tables+1];
      JOIN_TAB *end_table= &join.join_tab[join.tables];
      for (; table < end_table ; table++)
      {
957 958 959 960 961 962 963
	/*
	  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.
	*/
	if (table->select_cond || (table->keyuse && !table->on_expr))
unknown's avatar
unknown committed
964 965 966 967 968 969 970
	{
	  /* We have to sort all rows */
	  select_limit= HA_POS_ERROR;
	  break;
	}
      }
    }
unknown's avatar
unknown committed
971 972
    if (create_sort_index(&join.join_tab[join.const_tables],
			  group ? group : order,
unknown's avatar
unknown committed
973 974
			  select_limit, 
			  thd->select_limit))
975 976
    {
      if (!join.join_tab[join.const_tables].select->quick)
977
	goto err;
978
    }
unknown's avatar
unknown committed
979 980 981 982 983 984
  }
  join.having=having;				// Actually a parameter
  thd->proc_info="Sending data";
  error=do_select(&join,&fields,NULL,procedure);

err:
985
  thd->limit_found_rows = join.send_records;
986
  thd->examined_row_count = join.examined_rows;
unknown's avatar
unknown committed
987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001
  thd->proc_info="end";
  join.lock=0;					// It's faster to unlock later
  join_free(&join);
  thd->proc_info="end2";			// QQ
  if (tmp_table)
    free_tmp_table(thd,tmp_table);
  thd->proc_info="end3";			// QQ
  delete select;
  delete_dynamic(&keyuse);
  delete procedure;
  thd->proc_info="end4";			// QQ
  DBUG_RETURN(error);
}

/*****************************************************************************
1002 1003
  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
1004 1005 1006
*****************************************************************************/

static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table,
unknown's avatar
unknown committed
1007
				      key_map keys,ha_rows limit)
unknown's avatar
unknown committed
1008 1009 1010 1011 1012 1013 1014
{
  int error;
  DBUG_ENTER("get_quick_record_count");
  if (select)
  {
    select->head=table;
    table->reginfo.impossible_range=0;
unknown's avatar
unknown committed
1015
    if ((error=select->test_quick_select(keys,(table_map) 0,limit))
unknown's avatar
unknown committed
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
	== 1)
      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 */
}


1029 1030 1031 1032 1033 1034 1035 1036
/*
  Calculate the best possible join and initialize the join structure

  RETURN VALUES
  0	ok
  1	Fatal error
*/
  
unknown's avatar
unknown committed
1037 1038
static bool
make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
1039
		     DYNAMIC_ARRAY *keyuse_array)
unknown's avatar
unknown committed
1040 1041 1042
{
  int error;
  uint i,table_count,const_count,found_ref,refs,key,const_ref,eq_part;
1043
  table_map found_const_table_map,all_table_map;
unknown's avatar
unknown committed
1044 1045 1046 1047 1048 1049 1050 1051
  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;
1052 1053
  stat=(JOIN_TAB*) join->thd->calloc(sizeof(JOIN_TAB)*table_count);
  stat_ref=(JOIN_TAB**) join->thd->alloc(sizeof(JOIN_TAB*)*MAX_TABLES);
1054
  table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*(table_count*2));
unknown's avatar
unknown committed
1055 1056 1057 1058 1059 1060
  if (!stat || !stat_ref || !table_vector)
    DBUG_RETURN(1);				// Eom /* purecov: inspected */

  join->best_ref=stat_vector;

  stat_end=stat+table_count;
1061
  found_const_table_map=all_table_map=0;
unknown's avatar
unknown committed
1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
  const_count=0;

  for (s=stat,i=0 ; tables ; s++,tables=tables->next,i++)
  {
    TABLE *table;
    stat_vector[i]=s;
    table_vector[i]=s->table=table=tables->table;
    table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);// record count
    table->quick_keys=0;
    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;
1075
    s->join=join;
1076
    s->info=0;					// For describe
unknown's avatar
unknown committed
1077 1078
    if ((s->on_expr=tables->on_expr))
    {
1079
      /* Left join */
unknown's avatar
unknown committed
1080 1081
      if (!table->file->records)
      {						// Empty table
1082
	s->key_dependent=s->dependent=0;	// Ignore LEFT JOIN depend.
unknown's avatar
unknown committed
1083 1084 1085
	set_position(join,const_count++,s,(KEYUSE*) 0);
	continue;
      }
unknown's avatar
unknown committed
1086 1087
      s->key_dependent=s->dependent=
	s->on_expr->used_tables() & ~(table->map);
1088 1089 1090 1091
      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
1092 1093 1094 1095 1096 1097 1098 1099
      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
1100
    if ((table->system || table->file->records <= 1) && ! s->dependent &&
1101
	!(table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
unknown's avatar
unknown committed
1102
        !table->fulltext_searched)
unknown's avatar
unknown committed
1103 1104 1105 1106 1107
    {
      set_position(join,const_count++,s,(KEYUSE*) 0);
    }
  }
  stat_vector[i]=0;
1108
  join->outer_join=outer_join;
unknown's avatar
unknown committed
1109 1110

  /*
1111 1112 1113 1114
    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
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
  */
  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)
1147
    if (update_ref_and_keys(join->thd,keyuse_array,stat,join->tables,
1148
                            conds,~outer_join))
unknown's avatar
unknown committed
1149 1150
      DBUG_RETURN(1);

1151
  /* Read tables with 0 or 1 rows (system tables) */
1152
  join->const_table_map= 0;
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170

  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
1171
  /* loop until no more const tables are found */
1172
  int ref_changed;
unknown's avatar
unknown committed
1173 1174
  do
  {
1175
    ref_changed = 0;
unknown's avatar
unknown committed
1176
    found_ref=0;
1177 1178 1179 1180 1181 1182 1183

    /*
      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
1184
    {
1185
      TABLE *table=s->table;
unknown's avatar
unknown committed
1186 1187
      if (s->dependent)				// If dependent on some table
      {
1188
	// All dep. must be constants
1189
	if (s->dependent & ~(found_const_table_map))
unknown's avatar
unknown committed
1190
	  continue;
1191
	if (table->file->records <= 1L &&
1192
	    !(table->file->table_flags() & HA_NOT_EXACT_COUNT))
unknown's avatar
unknown committed
1193
	{					// system table
1194
	  int tmp= 0;
unknown's avatar
unknown committed
1195
	  s->type=JT_SYSTEM;
1196
	  join->const_table_map|=table->map;
unknown's avatar
unknown committed
1197
	  set_position(join,const_count++,s,(KEYUSE*) 0);
1198
	  if ((tmp= join_read_const_table(s,join->positions+const_count-1)))
1199 1200 1201 1202 1203 1204
	  {
	    if (tmp > 0)
	      DBUG_RETURN(1);			// Fatal error
	  }
	  else
	    found_const_table_map|= table->map;
unknown's avatar
unknown committed
1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
	  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;
	  s->keys|= (key_map) 1 << key;		// QQ: remove this ?

	  refs=const_ref=eq_part=0;
	  do
	  {
	    if (keyuse->val->type() != Item::NULL_ITEM)
	    {
1223
	      if (!((~found_const_table_map) & keyuse->used_tables))
unknown's avatar
unknown committed
1224 1225 1226 1227 1228 1229 1230 1231 1232
		const_ref|= (key_map) 1 << keyuse->keypart;
	      else
		refs|=keyuse->used_tables;
	      eq_part|= (uint) 1 << keyuse->keypart;
	    }
	    keyuse++;
	  } while (keyuse->table == table && keyuse->key == key);

	  if (eq_part == PREV_BITS(uint,table->key_info[key].key_parts) &&
unknown's avatar
unknown committed
1233 1234
	      (table->key_info[key].flags & HA_NOSAME) &&
              !table->fulltext_searched)
unknown's avatar
unknown committed
1235 1236 1237
	  {
	    if (const_ref == eq_part)
	    {					// Found everything for ref.
1238 1239
	      int tmp;
	      ref_changed = 1;
1240
	      s->type= JT_CONST;
1241
	      join->const_table_map|=table->map;
unknown's avatar
unknown committed
1242
	      set_position(join,const_count++,s,start_keyuse);
1243
	      if (create_ref_for_key(join, s, start_keyuse,
1244
				     found_const_table_map))
1245 1246 1247 1248 1249 1250 1251 1252 1253
		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
1254 1255 1256 1257 1258 1259 1260 1261
	      break;
	    }
	    else
	      found_ref|= refs;		// Table is const if all refs are const
	  }
	}
      }
    }
1262
  } while (join->const_table_map & found_ref && ref_changed);
unknown's avatar
unknown committed
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275

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

1278 1279
    /*
      Set a max range of how many seeks we can expect when using keys
1280 1281
      This is can't be to high as otherwise we are likely to use
      table scan.
1282
    */
1283 1284
    s->worst_seeks= min((double) s->found_records / 10,
			(double) s->read_time*3);
unknown's avatar
unknown committed
1285 1286 1287 1288 1289 1290
    if (s->worst_seeks < 2.0)			// Fix for small tables
      s->worst_seeks=2.0;

    if (s->const_keys)
    {
      ha_rows records;
1291 1292 1293 1294 1295 1296 1297
      SQL_SELECT *select;
      select= make_select(s->table, found_const_table_map,
			  found_const_table_map,
			  s->on_expr ? s->on_expr : conds,
			  &error);
      records= get_quick_record_count(select,s->table, s->const_keys,
				      join->row_limit);
unknown's avatar
unknown committed
1298 1299 1300
      s->quick=select->quick;
      s->needed_reg=select->needed_reg;
      select->quick=0;
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320
      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
1321 1322
      if (records != HA_POS_ERROR)
      {
1323
	s->found_records=records;
unknown's avatar
unknown committed
1324 1325
	s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
      }
1326
      delete select;
unknown's avatar
unknown committed
1327 1328 1329 1330 1331 1332 1333 1334
    }
  }

  /* 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;
1335
  join->found_const_table_map=found_const_table_map;
unknown's avatar
unknown committed
1336 1337

  if (join->const_tables != join->tables)
1338
    find_best_combination(join,all_table_map & ~join->const_table_map);
unknown's avatar
unknown committed
1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349
  else
  {
    memcpy((gptr) join->best_positions,(gptr) join->positions,
	   sizeof(POSITION)*join->const_tables);
    join->best_read=1.0;
  }
  DBUG_RETURN(get_best_combination(join));
}


/*****************************************************************************
1350 1351 1352 1353 1354
  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
1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
*****************************************************************************/

typedef struct key_field_t {		// Used when finding key fields
  Field		*field;
  Item		*val;			// May be empty if diff constant
  uint		level,const_level;	// QQ: Remove const_level
  bool		eq_func;
  bool		exists_optimize;
} KEY_FIELD;


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

static KEY_FIELD *
merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
		 uint and_level)
{
  if (start == new_fields)
unknown's avatar
unknown committed
1373
    return start;				// Impossible or
unknown's avatar
unknown committed
1374
  if (new_fields == end)
unknown's avatar
unknown committed
1375
    return start;				// No new fields, skip all
unknown's avatar
unknown committed
1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387

  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())
	{
1388
	  if (old->val->eq(new_fields->val, old->field->binary()))
unknown's avatar
unknown committed
1389 1390 1391 1392 1393
	  {
	    old->level=old->const_level=and_level;
	    old->exists_optimize&=new_fields->exists_optimize;
	  }
	}
1394 1395
	else if (old->val->eq(new_fields->val, old->field->binary()) &&
		 old->eq_func && new_fields->eq_func)
unknown's avatar
unknown committed
1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
	{
	  old->level=old->const_level=and_level;
	  old->exists_optimize&=new_fields->exists_optimize;
	}
	else					// Impossible; remove it
	{
	  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 ;)
  {
    if (old->level != and_level && old->const_level != and_level)
    {						// Not used in all levels
      if (old == --first_free)
	break;
      *old= *first_free;			// Remove old value
      continue;
    }
    old++;
  }
unknown's avatar
unknown committed
1422
  return first_free;
unknown's avatar
unknown committed
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436
}


static void
add_key_field(KEY_FIELD **key_fields,uint and_level,
	      Field *field,bool eq_func,Item *value,
	      table_map usable_tables)
{
  bool exists_optimize=0;
  if (!(field->flags & PART_KEY_FLAG))
  {
    // Don't remove column IS NULL on a LEFT JOIN table
    if (!eq_func || !value || value->type() != Item::NULL_ITEM ||
	!field->table->maybe_null || field->null_ptr)
unknown's avatar
unknown committed
1437
      return;					// Not a key. Skip it
unknown's avatar
unknown committed
1438 1439 1440 1441 1442 1443 1444
    exists_optimize=1;
  }
  else
  {
    table_map used_tables=0;
    if (value && (used_tables=value->used_tables()) &
	(field->table->map | RAND_TABLE_BIT))
unknown's avatar
unknown committed
1445
      return;
unknown's avatar
unknown committed
1446 1447 1448 1449
    if (!(usable_tables & field->table->map))
    {
      if (!eq_func || !value || value->type() != Item::NULL_ITEM ||
	  !field->table->maybe_null || field->null_ptr)
unknown's avatar
unknown committed
1450
	return;					// Can't use left join optimize
unknown's avatar
unknown committed
1451 1452 1453 1454 1455
      exists_optimize=1;
    }
    else
    {
      JOIN_TAB *stat=field->table->reginfo.join_tab;
unknown's avatar
unknown committed
1456 1457 1458
      key_map possible_keys= (field->key_start &
			      field->table->keys_in_use_for_query);
      stat[0].keys|= possible_keys;		// Add possible keys
unknown's avatar
unknown committed
1459 1460 1461

      if (!value)
      {						// Probably BETWEEN or IN
unknown's avatar
unknown committed
1462
	stat[0].const_keys |= possible_keys;
unknown's avatar
unknown committed
1463
	return;					// Can't be used as eq key
unknown's avatar
unknown committed
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475
      }

      /* 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
      */
      stat[0].key_dependent|=used_tables;
      if (value->const_item())
unknown's avatar
unknown committed
1476
	stat[0].const_keys |= possible_keys;
unknown's avatar
unknown committed
1477 1478 1479 1480 1481 1482 1483

      /* We can't always use indexes when comparing a string index to a
	 number. cmp_type() is checked to allow compare of dates to numbers */
      if (!eq_func ||
	  field->result_type() == STRING_RESULT &&
	  value->result_type() != STRING_RESULT &&
	  field->cmp_type() != value->result_type())
unknown's avatar
unknown committed
1484
	return;
unknown's avatar
unknown committed
1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502
    }
  }
  /* Store possible eq field */
  (*key_fields)->field=field;
  (*key_fields)->eq_func=eq_func;
  (*key_fields)->val=value;
  (*key_fields)->level=(*key_fields)->const_level=and_level;
  (*key_fields)->exists_optimize=exists_optimize;
  (*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
1503
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532
    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++)
      {
	if (org_key_fields->const_level == org_key_fields->level)
	  org_key_fields->const_level=org_key_fields->level= *and_level;
	else
	  org_key_fields->const_level= *and_level;
      }
    }
    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));
      }
    }
unknown's avatar
unknown committed
1533
    return;
unknown's avatar
unknown committed
1534 1535 1536 1537
  }
  /* If item is of type 'field op field/constant' add it to key_fields */

  if (cond->type() != Item::FUNC_ITEM)
unknown's avatar
unknown committed
1538
    return;
unknown's avatar
unknown committed
1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581
  Item_func *cond_func= (Item_func*) cond;
  switch (cond_func->select_optimize()) {
  case Item_func::OPTIMIZE_NONE:
    break;
  case Item_func::OPTIMIZE_KEY:
    if (cond_func->key_item()->type() == Item::FIELD_ITEM)
      add_key_field(key_fields,*and_level,
		    ((Item_field*) (cond_func->key_item()))->field,
		    0,(Item*) 0,usable_tables);
    break;
  case Item_func::OPTIMIZE_OP:
  {
    bool equal_func=(cond_func->functype() == Item_func::EQ_FUNC ||
		     cond_func->functype() == Item_func::EQUAL_FUNC);

    if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
    {
      add_key_field(key_fields,*and_level,
		    ((Item_field*) (cond_func->arguments()[0]))->field,
		    equal_func,
		    (cond_func->arguments()[1]),usable_tables);
    }
    if (cond_func->arguments()[1]->type() == Item::FIELD_ITEM &&
	cond_func->functype() != Item_func::LIKE_FUNC)
    {
      add_key_field(key_fields,*and_level,
		    ((Item_field*) (cond_func->arguments()[1]))->field,
		    equal_func,
		    (cond_func->arguments()[0]),usable_tables);
    }
    break;
  }
  case Item_func::OPTIMIZE_NULL:
    /* column_name IS [NOT] NULL */
    if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
    {
      add_key_field(key_fields,*and_level,
		    ((Item_field*) (cond_func->arguments()[0]))->field,
		    cond_func->functype() == Item_func::ISNULL_FUNC,
		    new Item_null, usable_tables);
    }
    break;
  }
unknown's avatar
unknown committed
1582
  return;
unknown's avatar
unknown committed
1583 1584 1585
}

/*
1586 1587
  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
1588 1589 1590 1591 1592 1593 1594
*/

static uint
max_part_bit(key_map bits)
{
  uint found;
  for (found=0; bits & 1 ; found++,bits>>=1) ;
unknown's avatar
unknown committed
1595
  return found;
unknown's avatar
unknown committed
1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635
}


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

  if (key_field->eq_func && !key_field->exists_optimize)
  {
    for (uint key=0 ; key < form->keys ; key++)
    {
      if (!(form->keys_in_use_for_query & (((key_map) 1) << key)))
	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;
	  keyuse.used_tables=key_field->val->used_tables();
	  VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
	}
      }
    }
  }
  /* Mark that we can optimize LEFT JOIN */
  if (key_field->val->type() == Item::NULL_ITEM &&
      !key_field->field->real_maybe_null())
    key_field->field->table->reginfo.not_exists_optimize=1;
}

unknown's avatar
unknown committed
1636 1637 1638

#define FT_KEYPART   (MAX_REF_PARTS+10)

unknown's avatar
unknown committed
1639 1640 1641 1642
static void
add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
            JOIN_TAB *stat,COND *cond,table_map usable_tables)
{
1643
  Item_func_match *cond_func=NULL;
unknown's avatar
unknown committed
1644

1645
  if (!cond)
unknown's avatar
unknown committed
1646
    return;
1647

1648 1649
  if (cond->type() == Item::FUNC_ITEM)
  {
1650 1651 1652
    Item_func *func=(Item_func *)cond;
    Item_func::Functype functype=  func->functype();
    if (functype == Item_func::FT_FUNC)
1653
      cond_func=(Item_func_match *)cond;
1654 1655 1656 1657
    else if (func->arg_count == 2)
    {
      Item_func *arg0=(Item_func *)(func->arguments()[0]),
                *arg1=(Item_func *)(func->arguments()[1]);
1658 1659 1660 1661 1662
      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)
1663
        cond_func=(Item_func_match *) arg0;
1664 1665 1666
      else if (arg0->const_item() &&
               ((functype == Item_func::LE_FUNC && arg0->val()> 0) ||
                (functype == Item_func::LT_FUNC && arg0->val()>=0)) &&
1667
                arg1->type() == Item::FUNC_ITEM          &&
1668
                arg1->functype() == Item_func::FT_FUNC)
1669 1670
        cond_func=(Item_func_match *) arg1;
    }
1671 1672 1673
  }
  else if (cond->type() == Item::COND_ITEM)
  {
unknown's avatar
unknown committed
1674
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
1675 1676 1677 1678

    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
    {
      Item *item;
1679
      /*
1680
         I'm (Sergei) too lazy to implement proper recursive descent here,
1681 1682 1683
         and anyway, nobody will use such a stupid queries
         that will require it :-)
         May be later...
1684
      */
1685
      while ((item=li++))
1686
      {
1687 1688 1689 1690 1691 1692
        if (item->type() == Item::FUNC_ITEM &&
            ((Item_func *)item)->functype() == Item_func::FT_FUNC)
        {
          cond_func=(Item_func_match *)item;
          break;
        }
1693
      }
1694 1695 1696
    }
  }

unknown's avatar
unknown committed
1697 1698
  if ((!cond_func || cond_func->key == NO_SUCH_KEY) ||
      (!(usable_tables & cond_func->table->map)))
unknown's avatar
unknown committed
1699 1700
    return;

unknown's avatar
unknown committed
1701 1702
  KEYUSE keyuse;
  keyuse.table= cond_func->table;
1703
  keyuse.val =  cond_func;
unknown's avatar
unknown committed
1704
  keyuse.key =  cond_func->key;
unknown's avatar
unknown committed
1705
  keyuse.keypart= FT_KEYPART;
1706
  keyuse.used_tables=cond_func->key_item()->used_tables();
unknown's avatar
unknown committed
1707 1708 1709
  VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
}

unknown's avatar
unknown committed
1710

unknown's avatar
unknown committed
1711 1712 1713 1714
static int
sort_keyuse(KEYUSE *a,KEYUSE *b)
{
  if (a->table->tablenr != b->table->tablenr)
unknown's avatar
unknown committed
1715
    return (int) (a->table->tablenr - b->table->tablenr);
unknown's avatar
unknown committed
1716
  if (a->key != b->key)
unknown's avatar
unknown committed
1717
    return (int) (a->key - b->key);
unknown's avatar
unknown committed
1718
  if (a->keypart != b->keypart)
unknown's avatar
unknown committed
1719 1720
    return (int) (a->keypart - b->keypart);
  return test(a->used_tables) - test(b->used_tables);	// Place const first
unknown's avatar
unknown committed
1721 1722 1723 1724
}


/*
1725 1726 1727
  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
1728 1729 1730
*/

static bool
1731
update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
1732
		    uint tables, COND *cond, table_map normal_tables)
unknown's avatar
unknown committed
1733 1734 1735 1736 1737 1738 1739
{
  uint	and_level,i,found_eq_constant;

  {
    KEY_FIELD *key_fields,*end;

    if (!(key_fields=(KEY_FIELD*)
unknown's avatar
unknown committed
1740
	  thd->alloc(sizeof(key_fields[0])*(thd->cond_count+1)*2)))
unknown's avatar
unknown committed
1741
      return TRUE; /* purecov: inspected */
unknown's avatar
unknown committed
1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752
    and_level=0; end=key_fields;
    if (cond)
      add_key_fields(join_tab,&end,&and_level,cond,normal_tables);
    for (i=0 ; i < tables ; i++)
    {
      if (join_tab[i].on_expr)
      {
	add_key_fields(join_tab,&end,&and_level,join_tab[i].on_expr,
		       join_tab[i].table->map);
      }
    }
1753
    if (my_init_dynamic_array(keyuse,sizeof(KEYUSE),20,64))
unknown's avatar
unknown committed
1754
      return TRUE;
unknown's avatar
unknown committed
1755 1756 1757 1758 1759
    /* fill keyuse with found key parts */
    for (KEY_FIELD *field=key_fields ; field != end ; field++)
      add_key_part(keyuse,field);
  }

1760
  if (thd->lex.select->ftfunc_list.elements)
unknown's avatar
unknown committed
1761 1762 1763 1764 1765
  {
    add_ft_keys(keyuse,join_tab,cond,normal_tables);
  }

  /*
1766 1767 1768
    Remove ref if there is a keypart which is a ref and a const.
    Remove keyparts without previous keyparts.
    Special treatment for ft-keys.
unknown's avatar
unknown committed
1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785
  */
  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)
1786
	use->table->const_key_parts[use->key] |=
unknown's avatar
unknown committed
1787 1788 1789
	  (key_part_map) 1 << use->keypart;
      if (use->keypart != FT_KEYPART)
      {
1790 1791 1792 1793 1794 1795 1796 1797
	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
1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812
      }

      *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;
      use->table->reginfo.join_tab->checked_keys|= (key_map) 1 << use->key;
      save_pos++;
    }
    i=(uint) (save_pos-(KEYUSE*) keyuse->buffer);
    VOID(set_dynamic(keyuse,(gptr) &end,i));
    keyuse->elements=i;
  }
unknown's avatar
unknown committed
1813
  return FALSE;
unknown's avatar
unknown committed
1814 1815 1816 1817
}


/*****************************************************************************
1818 1819
  Go through all combinations of not marked tables and find the one
  which uses least records
unknown's avatar
unknown committed
1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833
*****************************************************************************/

/* 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];
1834
  for (;next != table ; pos++)
unknown's avatar
unknown committed
1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857
  {
    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)
{
1858
  ha_rows rec;
unknown's avatar
unknown committed
1859
  double tmp;
unknown's avatar
unknown committed
1860
  THD *thd= join->thd;
unknown's avatar
unknown committed
1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876

  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 &&
	join->sort_by_table != join->positions[join->const_tables].table->table)
      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;
    }
unknown's avatar
unknown committed
1877
    return;
unknown's avatar
unknown committed
1878 1879
  }
  if (read_time+record_count/(double) TIME_FOR_COMPARE >= join->best_read)
unknown's avatar
unknown committed
1880
    return;					/* Found better before */
unknown's avatar
unknown committed
1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891

  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;
1892
      uint best_max_key_part=0;
1893
      my_bool found_constrain= 0;
unknown's avatar
unknown committed
1894 1895 1896 1897 1898 1899

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

	/* Test how we can use keys */
1903
	rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE;  /* Assumed records/key */
unknown's avatar
unknown committed
1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917
	for (keyuse=s->keyuse ; keyuse->table == table ;)
	{
	  key_map found_part=0;
	  table_map found_ref=0;
	  uint key=keyuse->key;
	  KEY *keyinfo=table->key_info+key;
          bool ft_key=(keyuse->keypart == FT_KEYPART);

	  start_key=keyuse;
	  do
	  {
            uint keypart=keyuse->keypart;
	    do
	    {
1918
              if (!ft_key)
unknown's avatar
unknown committed
1919
              {
1920 1921
		table_map map;
		if (!(rest_tables & keyuse->used_tables))
unknown's avatar
unknown committed
1922
		{
1923 1924 1925 1926
		  found_part|= (key_part_map) 1 << keypart;
		  found_ref|= keyuse->used_tables;
		}
		/*
1927 1928 1929 1930 1931 1932
		  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 and to avoid bad matches,
		  we don't make rec less than 100.
1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944
		*/
		if (keyuse->used_tables &
		    (map=(keyuse->used_tables & ~join->const_table_map)))
		{
		  uint tablenr;
		  for (tablenr=0 ; ! (map & 1) ; map>>=1, tablenr++) ;
		  if (map == 1)			// Only one table
		  {
		    TABLE *tmp_table=join->all_tables[tablenr];
		    if (rec > tmp_table->file->records && rec > 100)
		      rec=max(tmp_table->file->records,100);
		  }
unknown's avatar
unknown committed
1945 1946 1947 1948 1949 1950 1951 1952
		}
              }
	      keyuse++;
	    } while (keyuse->table == table && keyuse->key == key &&
		     keyuse->keypart == keypart);
	  } while (keyuse->table == table && keyuse->key == key);

	  /*
1953
	    Assume that that each key matches a proportional part of table.
unknown's avatar
unknown committed
1954 1955 1956 1957 1958 1959 1960
	  */
          if (!found_part && !ft_key)
	    continue;				// Nothing usable found
	  if (rec == 0)
	    rec=1L;				// Fix for small tables

          /*
1961
	    ft-keys require special treatment
unknown's avatar
unknown committed
1962 1963 1964 1965
          */
          if (ft_key)
          {
            /*
1966 1967
	      Really, there should be records=0.0 (yes!)
	      but 1.0 would be probably safer
unknown's avatar
unknown committed
1968 1969 1970 1971 1972 1973
            */
            tmp=prev_record_reads(join,found_ref);
            records=1.0;
          }
          else
          {
1974
	  found_constrain= 1;
unknown's avatar
unknown committed
1975
	  /*
1976
	    Check if we found full key
unknown's avatar
unknown committed
1977 1978 1979
	  */
	  if (found_part == PREV_BITS(uint,keyinfo->key_parts))
	  {				/* use eq key */
1980
	    max_key_part= (uint) ~0;
unknown's avatar
unknown committed
1981 1982 1983 1984 1985 1986 1987
	    if ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
	    {
	      tmp=prev_record_reads(join,found_ref);
	      records=1.0;
	    }
	    else
	    {
1988 1989
	      if (!found_ref)
	      {					// We found a const key
unknown's avatar
unknown committed
1990 1991 1992
		if (table->quick_keys & ((key_map) 1 << key))
		  records= (double) table->quick_rows[key];
		else
unknown's avatar
unknown committed
1993 1994 1995 1996
		{
		  /* quick_range couldn't use key! */
		  records= (double) s->records/rec;
		}
unknown's avatar
unknown committed
1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010
	      }
	      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
		}
	      }
2011 2012 2013
	      /* Limit the number of matched rows */
	      tmp= records;
	      set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
unknown's avatar
unknown committed
2014 2015 2016 2017
	      if (table->used_keys & ((key_map) 1 << key))
	      {
		/* we can use only index tree */
		uint keys_per_block= table->file->block_size/2/
unknown's avatar
unknown committed
2018
		  (keyinfo->key_length+table->file->ref_length)+1;
2019
		tmp=record_count*(tmp+keys_per_block-1)/keys_per_block;
unknown's avatar
unknown committed
2020 2021
	      }
	      else
2022
		tmp=record_count*min(tmp,s->worst_seeks);
unknown's avatar
unknown committed
2023 2024 2025 2026 2027
	    }
	  }
	  else
	  {
	    /*
2028 2029 2030
	      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
2031
	    */
2032
	    if ((found_part & 1) &&
2033
		!(table->file->index_flags(key) & HA_ONLY_WHOLE_INDEX))
unknown's avatar
unknown committed
2034
	    {
2035
	      max_key_part=max_part_bit(found_part);
2036 2037 2038 2039
	      /*
		Check if quick_range could determinate how many rows we
		will match
	      */
unknown's avatar
unknown committed
2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050
	      if (table->quick_keys & ((key_map) 1 << key) &&
		  table->quick_key_parts[key] <= max_key_part)
		tmp=records= (double) table->quick_rows[key];
	      else
	      {
		/* Check if we have statistic about the distribution */
		if ((records=keyinfo->rec_per_key[max_key_part-1]))
		  tmp=records;
		else
		{
		  /*
2051
		    Assume that the first key part matches 1% of the file
2052
		    and that the hole key matches 10 (duplicates) or 1
2053 2054 2055 2056 2057
		    (unique) records.
		    Assume also that more key matches proportionally more
		    records
		    This gives the formula:
		    records= (x * (b-a) + a*c-b)/(c-1)
2058

2059 2060 2061 2062
		    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
2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083
		  */
		  double rec_per_key;
		  if (!(rec_per_key=(double)
			keyinfo->rec_per_key[keyinfo->key_parts-1]))
		    rec_per_key=(double) s->records/rec+1;

		  if (!s->records)
		    tmp=0;
		  else if (rec_per_key/(double) s->records >= 0.01)
		    tmp=rec_per_key;
		  else
		  {
		    double a=s->records*0.01;
		    tmp=(max_key_part * (rec_per_key - a) +
			 a*keyinfo->key_parts - rec_per_key)/
		      (keyinfo->key_parts-1);
		    set_if_bigger(tmp,1.0);
		  }
		  records=(ulong) tmp;
		}
	      }
2084 2085
	      /* Limit the number of matched rows */
	      set_if_smaller(tmp, (double) thd->variables.max_seeks_for_key);
unknown's avatar
unknown committed
2086 2087 2088 2089
	      if (table->used_keys & ((key_map) 1 << key))
	      {
		/* we can use only index tree */
		uint keys_per_block= table->file->block_size/2/
unknown's avatar
unknown committed
2090
		  (keyinfo->key_length+table->file->ref_length)+1;
unknown's avatar
unknown committed
2091 2092 2093 2094 2095 2096 2097 2098
		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
	  }
2099
          } /* not ft_key */
unknown's avatar
unknown committed
2100 2101 2102 2103 2104 2105
	  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;
2106
	    best_max_key_part=max_key_part;
unknown's avatar
unknown committed
2107 2108 2109 2110
	  }
	}
	records=best_records;
      }
2111 2112 2113 2114

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

	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.
2120 2121 2122
      */
      if ((records >= s->found_records || best > s->read_time) &&
	  !(s->quick && best_key && s->quick->index == best_key->key &&
2123
	    best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&
2124
	  !((s->table->file->table_flags() & HA_TABLE_SCAN_ON_INDEX) &&
2125 2126
	    s->table->used_keys && best_key) &&
	  !(s->table->force_index && best_key))
unknown's avatar
unknown committed
2127
      {						// Check full join
2128
	ha_rows rnd_records= s->found_records;
unknown's avatar
unknown committed
2129 2130
	if (s->on_expr)
	{
2131
	  tmp=rows2double(rnd_records);		// Can't use read cache
unknown's avatar
unknown committed
2132 2133 2134 2135
	}
	else
	{
	  tmp=(double) s->read_time;
2136
	  /* Calculate time to read previous rows through cache */
unknown's avatar
unknown committed
2137
	  tmp*=(1.0+floor((double) cache_record_length(join,idx)*
2138 2139
			  record_count /
			  (double) thd->variables.join_buff_size));
unknown's avatar
unknown committed
2140
	}
2141 2142 2143 2144 2145 2146 2147 2148 2149 2150

	/*
	  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_constrain)
	  rnd_records-= rnd_records/4;

unknown's avatar
unknown committed
2151
	if (best == DBL_MAX ||
2152
	    (tmp  + record_count/(double) TIME_FOR_COMPARE*rnd_records <
unknown's avatar
unknown committed
2153 2154
	     best + record_count/(double) TIME_FOR_COMPARE*records))
	{
2155 2156 2157 2158
	  /*
	    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
2159
	  best=tmp;
2160
	  records= rows2double(rnd_records);
unknown's avatar
unknown committed
2161 2162 2163
	  best_key=0;
	}
      }
2164
      join->positions[idx].records_read= records;
unknown's avatar
unknown committed
2165 2166 2167
      join->positions[idx].key=best_key;
      join->positions[idx].table= s;
      if (!best_key && idx == join->const_tables &&
unknown's avatar
unknown committed
2168 2169
	  s->table == join->sort_by_table &&
	  join->thd->select_limit >= records)
unknown's avatar
unknown committed
2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201
	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;
	}
	swap(JOIN_TAB*,join->best_ref[idx],*pos);
	find_best(join,rest_tables & ~real_table_bit,idx+1,
		  current_record_count,current_read_time);
	swap(JOIN_TAB*,join->best_ref[idx],*pos);
      }
      if (join->select_options & SELECT_STRAIGHT_JOIN)
	break;				// Don't test all combinations
    }
  }
}


/*
2202
  Find how much space the prevous read not const tables takes in cache
unknown's avatar
unknown committed
2203 2204
*/

2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239
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
2240 2241 2242
static uint
cache_record_length(JOIN *join,uint idx)
{
2243
  uint length=0;
unknown's avatar
unknown committed
2244
  JOIN_TAB **pos,**end;
2245
  THD *thd=join->thd;
unknown's avatar
unknown committed
2246 2247 2248 2249 2250 2251

  for (pos=join->best_ref+join->const_tables,end=join->best_ref+idx ;
       pos != end ;
       pos++)
  {
    JOIN_TAB *join_tab= *pos;
2252 2253
    if (!join_tab->used_fieldlength)		/* Not calced yet */
      calc_used_field_length(thd, join_tab);
unknown's avatar
unknown committed
2254 2255
    length+=join_tab->used_fieldlength;
  }
unknown's avatar
unknown committed
2256
  return length;
unknown's avatar
unknown committed
2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272
}


static double
prev_record_reads(JOIN *join,table_map found_ref)
{
  double found=1.0;

  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;
    }
  }
unknown's avatar
unknown committed
2273
  return found;
unknown's avatar
unknown committed
2274 2275 2276 2277
}


/*****************************************************************************
2278
  Set up join struct according to best position.
unknown's avatar
unknown committed
2279 2280 2281 2282 2283
*****************************************************************************/

static bool
get_best_combination(JOIN *join)
{
2284
  uint i,tablenr;
unknown's avatar
unknown committed
2285 2286 2287 2288
  table_map used_tables;
  JOIN_TAB *join_tab,*j;
  KEYUSE *keyuse;
  uint table_count;
2289
  THD *thd=join->thd;
unknown's avatar
unknown committed
2290 2291 2292

  table_count=join->tables;
  if (!(join->join_tab=join_tab=
2293
	(JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*table_count)))
unknown's avatar
unknown committed
2294
    return TRUE;
unknown's avatar
unknown committed
2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307

  join->full_join=0;

  used_tables=0;
  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
2308 2309 2310 2311 2312
    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
2313 2314 2315 2316 2317 2318 2319 2320 2321

    if (j->type == JT_SYSTEM)
      continue;
    if (!j->keys || !(keyuse= join->best_positions[tablenr].key))
    {
      j->type=JT_ALL;
      if (tablenr != join->const_tables)
	join->full_join=1;
    }
2322
    else if (create_ref_for_key(join, j, keyuse, used_tables))
unknown's avatar
unknown committed
2323
      return TRUE;				// Something went wrong
2324
  }
unknown's avatar
unknown committed
2325

2326 2327 2328
  for (i=0 ; i < table_count ; i++)
    join->map2table[join->join_tab[i].table->tablenr]=join->join_tab+i;
  update_depend_map(join);
unknown's avatar
unknown committed
2329
  return 0;
2330
}
2331

unknown's avatar
unknown committed
2332

2333 2334 2335 2336 2337 2338 2339 2340 2341
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;
2342

2343
  /*
2344
    Use best key from find_best
2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363
  */
  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;
    do
    {
      if (!((~used_tables) & keyuse->used_tables))
unknown's avatar
unknown committed
2364
      {
2365
	if (keyparts == keyuse->keypart)
unknown's avatar
unknown committed
2366
	{
2367 2368
	  keyparts++;
	  length+=keyinfo->key_part[keyuse->keypart].store_length;
unknown's avatar
unknown committed
2369 2370
	}
      }
2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384
      keyuse++;
    } while (keyuse->table == table && keyuse->key == key);
  } /* not ftkey */

  /* set up fieldref */
  keyinfo=table->key_info+key;
  j->ref.key_parts=keyparts;
  j->ref.key_length=length;
  j->ref.key=(int) key;
  if (!(j->ref.key_buff= (byte*) thd->calloc(ALIGN_SIZE(length)*2)) ||
      !(j->ref.key_copy= (store_key**) thd->alloc((sizeof(store_key*) *
						   (keyparts+1)))) ||
      !(j->ref.items=    (Item**) thd->alloc(sizeof(Item*)*keyparts)))
  {
unknown's avatar
unknown committed
2385
    return TRUE;
2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396
  }
  j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length);
  j->ref.key_err=1;
  keyuse=org_keyuse;

  store_key **ref_key=j->ref.key_copy;
  byte *key_buff=j->ref.key_buff;
  if (ftkey)
  {
    j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
    if (keyuse->used_tables)
unknown's avatar
unknown committed
2397
      return TRUE; // not supported yet. SerG
2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423

    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
      if (!keyuse->used_tables &&
	  !(join->select_options & SELECT_DESCRIBE))
      {					// Compare against constant
	store_key_item *tmp=new store_key_item(thd,
					       keyinfo->key_part[i].field,
					       (char*)key_buff +
					       maybe_null,
					       maybe_null ?
					       (char*) key_buff : 0,
					       keyinfo->key_part[i].length,
					       keyuse->val);
	if (thd->fatal_error)
unknown's avatar
unknown committed
2424
	{
unknown's avatar
unknown committed
2425
	  return TRUE;
unknown's avatar
unknown committed
2426
	}
2427
	tmp->copy();
unknown's avatar
unknown committed
2428 2429
      }
      else
2430 2431 2432 2433 2434
	*ref_key++= get_store_key(thd,
				  keyuse,join->const_table_map,
				  &keyinfo->key_part[i],
				  (char*) key_buff,maybe_null);
      key_buff+=keyinfo->key_part[i].store_length;
unknown's avatar
unknown committed
2435
    }
2436 2437 2438 2439 2440 2441 2442 2443 2444 2445
  } /* not ftkey */
  *ref_key=0;				// end_marker
  if (j->type == JT_FT)  /* no-op */;
  else if (j->type == JT_CONST)
    j->table->const_table=1;
  else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY))
	    != HA_NOSAME) ||
	   keyparts != keyinfo->key_parts)
    j->type=JT_REF;				/* Must read with repeat */
  else if (ref_key == j->ref.key_copy)
2446
  {
2447 2448 2449 2450 2451 2452 2453 2454
    /*
      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
2455
  }
2456 2457
  else
    j->type=JT_EQ_REF;
unknown's avatar
unknown committed
2458
  return 0;
unknown's avatar
unknown committed
2459 2460 2461
}


2462

unknown's avatar
unknown committed
2463
static store_key *
unknown's avatar
unknown committed
2464 2465
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
2466 2467 2468
{
  if (!((~used_tables) & keyuse->used_tables))		// if const item
  {
unknown's avatar
unknown committed
2469
    return new store_key_const_item(thd,
unknown's avatar
unknown committed
2470
				    key_part->field,
unknown's avatar
unknown committed
2471 2472 2473
				    key_buff + maybe_null,
				    maybe_null ? key_buff : 0,
				    key_part->length,
unknown's avatar
unknown committed
2474
				    keyuse->val);
unknown's avatar
unknown committed
2475 2476
  }
  else if (keyuse->val->type() == Item::FIELD_ITEM)
unknown's avatar
unknown committed
2477
    return new store_key_field(thd,
unknown's avatar
unknown committed
2478
			       key_part->field,
unknown's avatar
unknown committed
2479 2480 2481 2482
			       key_buff + maybe_null,
			       maybe_null ? key_buff : 0,
			       key_part->length,
			       ((Item_field*) keyuse->val)->field,
unknown's avatar
unknown committed
2483 2484
			       keyuse->val->full_name());
  return new store_key_item(thd,
unknown's avatar
unknown committed
2485
			    key_part->field,
unknown's avatar
unknown committed
2486 2487 2488
			    key_buff + maybe_null,
			    maybe_null ? key_buff : 0,
			    key_part->length,
unknown's avatar
unknown committed
2489
			    keyuse->val);
unknown's avatar
unknown committed
2490 2491 2492
}

/*
2493 2494
  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
2495 2496 2497 2498 2499
*/

bool
store_val_in_field(Field *field,Item *item)
{
2500
  bool error;
unknown's avatar
unknown committed
2501
  THD *thd=current_thd;
2502
  ha_rows cuted_fields=thd->cuted_fields;
unknown's avatar
unknown committed
2503
  thd->count_cuted_fields=1;
2504
  error= item->save_in_field(field, 1);
unknown's avatar
unknown committed
2505
  thd->count_cuted_fields=0;
2506
  return error || cuted_fields != thd->cuted_fields;
unknown's avatar
unknown committed
2507 2508 2509 2510 2511 2512 2513 2514 2515
}


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

2516 2517
  if (!(tableptr=(TABLE**) join->thd->alloc(sizeof(TABLE*))) ||
      !(join_tab=(JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
unknown's avatar
unknown committed
2518
    return TRUE;
unknown's avatar
unknown committed
2519 2520 2521 2522 2523
  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
2524 2525 2526
  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
2527 2528
  join->first_record=join->sort_and_group=0;
  join->sum_funcs=0;
unknown's avatar
unknown committed
2529
  join->send_records=(ha_rows) 0;
unknown's avatar
unknown committed
2530
  join->group=0;
2531
  join->do_send_rows = 1;
2532
  join->row_limit=join->thd->select_limit;
unknown's avatar
unknown committed
2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543

  join_tab->cache.buff=0;			/* No cacheing */
  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 */
  join_tab->keys= (uint) ~0;			/* test everything in quick */
  join_tab->info=0;
  join_tab->on_expr=0;
  join_tab->ref.key = -1;
unknown's avatar
unknown committed
2544 2545
  join_tab->not_used_in_distinct=0;
  join_tab->read_first_record= join_init_read_record;
2546
  join_tab->join=join;
unknown's avatar
unknown committed
2547
  bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
unknown's avatar
unknown committed
2548 2549
  tmp_table->status=0;
  tmp_table->null_row=0;
unknown's avatar
unknown committed
2550
  return FALSE;
unknown's avatar
unknown committed
2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567
}


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
    {						// 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())
2568 2569
      {
	DBUG_PRINT("info",("Found impossible WHERE condition"));
unknown's avatar
unknown committed
2570
	DBUG_RETURN(1);				// Impossible const condition
2571
      }
unknown's avatar
unknown committed
2572 2573 2574 2575 2576 2577
    }
    used_tables=(select->const_tables=join->const_table_map) | RAND_TABLE_BIT;
    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
2578 2579 2580 2581
      /*
	Following force including random expression in last table condition.
	It solve problem with select like SELECT * FROM t1 WHERE rand() > 0.5
      */
2582 2583
      if (i == join->tables-1)
	current_map|= RAND_TABLE_BIT;
2584
      bool use_quick_range=0;
unknown's avatar
unknown committed
2585
      used_tables|=current_map;
2586 2587

      if (tab->type == JT_REF && tab->quick &&
unknown's avatar
unknown committed
2588
	  (uint) tab->ref.key == tab->quick->index &&
2589 2590 2591 2592 2593 2594 2595
	  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;
	tab->ref.key_parts=0;		// Don't use ref key.
2596
	join->best_positions[i].records_read= rows2double(tab->quick->records);
2597 2598
      }

unknown's avatar
unknown committed
2599
      COND *tmp=make_cond_for_table(cond,used_tables,current_map);
2600 2601 2602 2603 2604 2605 2606 2607
      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
2608 2609 2610 2611
      if (tmp)
      {
	DBUG_EXECUTE("where",print_where(tmp,tab->table->table_name););
	SQL_SELECT *sel=tab->select=(SQL_SELECT*)
2612
	  join->thd->memdup((gptr) select, sizeof(SQL_SELECT));
unknown's avatar
unknown committed
2613 2614 2615 2616 2617 2618
	if (!sel)
	  DBUG_RETURN(1);			// End of memory
	tab->select_cond=sel->cond=tmp;
	sel->head=tab->table;
	if (tab->quick)
	{
2619 2620
	  /* Use quick key read if it's a constant and it's not used
	     with key reading */
2621 2622
	  if (tab->needed_reg == 0 && tab->type != JT_EQ_REF
	      && tab->type != JT_FT && (tab->type != JT_REF ||
unknown's avatar
unknown committed
2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640
	       (uint) tab->ref.key == tab->quick->index))
	  {
	    sel->quick=tab->quick;		// Use value from get_quick_...
	    sel->quick_keys=0;
	    sel->needed_reg=0;
	  }
	  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)
	{
	  if (tab->const_keys && tab->table->reginfo.impossible_range)
	    DBUG_RETURN(1);
	}
2641
	else if (tab->type == JT_ALL && ! use_quick_range)
unknown's avatar
unknown committed
2642 2643 2644 2645 2646 2647
	{
	  if (tab->const_keys &&
	      tab->table->reginfo.impossible_range)
	    DBUG_RETURN(1);				// Impossible range
	  /*
	    We plan to scan all rows.
2648 2649 2650
	    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
2651 2652 2653
	  */

	  if ((tab->keys & ~ tab->const_keys && i > 0) ||
2654 2655 2656
	      (tab->const_keys && i == join->const_tables &&
	       join->thd->select_limit < join->best_positions[i].records_read &&
	       !(join->select_options & OPTION_FOUND_ROWS)))
unknown's avatar
unknown committed
2657
	  {
2658 2659 2660
	    /* Join with outer join condition */
	    COND *orig_cond=sel->cond;
	    sel->cond=and_conds(sel->cond,tab->on_expr);
unknown's avatar
unknown committed
2661 2662
	    if (sel->test_quick_select(tab->keys,
				       used_tables & ~ current_map,
2663 2664 2665 2666
				       (join->select_options &
					OPTION_FOUND_ROWS ?
					HA_POS_ERROR :
					join->thd->select_limit)) < 0)
2667 2668
	      DBUG_RETURN(1);				// Impossible range
	    sel->cond=orig_cond;
2669 2670 2671
	    /* Fix for EXPLAIN */
	    if (sel->quick)
	      join->best_positions[i].records_read= sel->quick->records;
unknown's avatar
unknown committed
2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685
	  }
	  else
	  {
	    sel->needed_reg=tab->needed_reg;
	    sel->quick_keys=0;
	  }
	  if ((sel->quick_keys | sel->needed_reg) & ~tab->checked_keys)
	  {
	    tab->keys=sel->quick_keys | sel->needed_reg;
	    tab->use_quick= (sel->needed_reg &&
			     (!select->quick_keys ||
			      (select->quick &&
			       (select->quick->records >= 100L)))) ?
	      2 : 1;
unknown's avatar
unknown committed
2686
	    sel->read_tables= used_tables & ~current_map;
unknown's avatar
unknown committed
2687 2688 2689 2690 2691 2692 2693 2694 2695
	  }
	  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"););
2696 2697
	      tab->cache.select=(SQL_SELECT*)
		join->thd->memdup((gptr) sel, sizeof(SQL_SELECT));
unknown's avatar
unknown committed
2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713
	      tab->cache.select->cond=tmp;
	      tab->cache.select->read_tables=join->const_table_map;
	    }
	  }
	}
      }
    }
  }
  DBUG_RETURN(0);
}


static void
make_join_readinfo(JOIN *join,uint options)
{
  uint i;
unknown's avatar
unknown committed
2714
  SELECT_LEX *select_lex = &(join->thd->lex.select_lex);
unknown's avatar
unknown committed
2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736
  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;
      break;
    case JT_EQ_REF:
      table->status=STATUS_NO_RECORD;
2737 2738 2739 2740 2741
      if (tab->select)
      {
	delete tab->select->quick;
	tab->select->quick=0;
      }
unknown's avatar
unknown committed
2742 2743 2744 2745 2746
      delete tab->quick;
      tab->quick=0;
      table->file->index_init(tab->ref.key);
      tab->read_first_record= join_read_key;
      tab->read_record.read_record= join_no_more_records;
unknown's avatar
unknown committed
2747 2748
      if (table->used_keys & ((key_map) 1 << tab->ref.key) &&
	  !table->no_keyread)
unknown's avatar
unknown committed
2749 2750 2751 2752 2753 2754 2755
      {
	table->key_read=1;
	table->file->extra(HA_EXTRA_KEYREAD);
      }
      break;
    case JT_REF:
      table->status=STATUS_NO_RECORD;
2756 2757 2758 2759 2760
      if (tab->select)
      {
	delete tab->select->quick;
	tab->select->quick=0;
      }
unknown's avatar
unknown committed
2761 2762 2763 2764
      delete tab->quick;
      tab->quick=0;
      table->file->index_init(tab->ref.key);
      tab->read_first_record= join_read_always_key;
2765
      tab->read_record.read_record= join_read_next_same;
unknown's avatar
unknown committed
2766 2767
      if (table->used_keys & ((key_map) 1 << tab->ref.key) &&
	  !table->no_keyread)
unknown's avatar
unknown committed
2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780
      {
	table->key_read=1;
	table->file->extra(HA_EXTRA_KEYREAD);
      }
      break;
    case JT_FT:
      table->status=STATUS_NO_RECORD;
      table->file->index_init(tab->ref.key);
      tab->read_first_record= join_ft_read_first;
      tab->read_record.read_record= join_ft_read_next;
      break;
    case JT_ALL:
      /*
2781
	If previous table use cache
unknown's avatar
unknown committed
2782 2783
      */
      table->status=STATUS_NO_RECORD;
unknown's avatar
unknown committed
2784
      if (i != join->const_tables && !(options & SELECT_NO_JOIN_CACHE) &&
unknown's avatar
unknown committed
2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795
	  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)
2796
      {
unknown's avatar
unknown committed
2797
	select_lex->options|=QUERY_NO_GOOD_INDEX_USED;
unknown's avatar
unknown committed
2798
	tab->read_first_record= join_init_quick_read_record;
2799 2800
	statistic_increment(select_range_check_count, &LOCK_status);
      }
unknown's avatar
unknown committed
2801 2802 2803
      else
      {
	tab->read_first_record= join_init_read_record;
2804 2805 2806 2807 2808 2809 2810 2811
	if (i == join->const_tables)
	{
	  if (tab->select && tab->select->quick)
	  {
	    statistic_increment(select_range_count, &LOCK_status);
	  }
	  else
	  {
unknown's avatar
unknown committed
2812
	    select_lex->options|=QUERY_NO_INDEX_USED;
2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823
	    statistic_increment(select_scan_count, &LOCK_status);
	  }
	}
	else
	{
	  if (tab->select && tab->select->quick)
	  {
	    statistic_increment(select_full_range_join_count, &LOCK_status);
	  }
	  else
	  {
unknown's avatar
unknown committed
2824
	    select_lex->options|=QUERY_NO_INDEX_USED;
2825 2826 2827
	    statistic_increment(select_full_join_count, &LOCK_status);
	  }
	}
unknown's avatar
unknown committed
2828
	if (!table->no_keyread)
unknown's avatar
unknown committed
2829
	{
unknown's avatar
unknown committed
2830 2831 2832 2833 2834 2835 2836 2837 2838 2839
	  if (tab->select && tab->select->quick &&
	      table->used_keys & ((key_map) 1 << tab->select->quick->index))
	  {
	    table->key_read=1;
	    table->file->extra(HA_EXTRA_KEYREAD);
	  }
	  else if (table->used_keys && ! (tab->select && tab->select->quick))
	  {					// Only read index tree
	    tab->index=find_shortest_key(table, table->used_keys);
	    tab->table->file->index_init(tab->index);
2840
	    tab->read_first_record= join_read_first;
unknown's avatar
unknown committed
2841 2842
	    tab->type=JT_NEXT;		// Read with index_first / index_next
	  }
unknown's avatar
unknown committed
2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858
	}
      }
      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
2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880
/*
  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++)
  {
2881
    if (tab->type == JT_ALL && (!tab->select || !tab->select->quick))
unknown's avatar
unknown committed
2882 2883 2884 2885 2886 2887 2888 2889 2890
    {
      my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,MYF(0));
      return(1);
    }
  }
  return(0);
}


unknown's avatar
unknown committed
2891 2892 2893 2894
static void
join_free(JOIN *join)
{
  JOIN_TAB *tab,*end;
unknown's avatar
unknown committed
2895
  DBUG_ENTER("join_free");
unknown's avatar
unknown committed
2896 2897 2898

  if (join->table)
  {
2899 2900 2901 2902 2903
    /*
      Only a sorted table may be cached.  This sorted table is always the
      first non const table in join->table
    */
    if (join->tables > join->const_tables) // Test for not-const tables
unknown's avatar
unknown committed
2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916
      free_io_cache(join->table[join->const_tables]);
    for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
    {
      delete tab->select;
      delete tab->quick;
      x_free(tab->cache.buff);
      if (tab->table)
      {
	if (tab->table->key_read)
	{
	  tab->table->key_read=0;
	  tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
	}
unknown's avatar
unknown committed
2917 2918 2919
	/* Don't free index if we are using read_record */
	if (!tab->read_record.table)
	  tab->table->file->index_end();
unknown's avatar
unknown committed
2920
      }
unknown's avatar
unknown committed
2921
      end_read_record(&tab->read_record);
unknown's avatar
unknown committed
2922 2923 2924
    }
    join->table=0;
  }
2925 2926 2927 2928
  /*
    We are not using tables anymore
    Unlock all tables. We may be in an INSERT .... SELECT statement.
  */
unknown's avatar
unknown committed
2929 2930
  if (join->lock && join->thd->lock &&
      !(join->select_options & SELECT_NO_UNLOCK))
unknown's avatar
unknown committed
2931 2932 2933 2934 2935 2936
  {
    mysql_unlock_read_tables(join->thd, join->lock);// Don't free join->lock
    join->lock=0;
  }
  join->group_fields.delete_elements();
  join->tmp_table_param.copy_funcs.delete_elements();
2937
  join->tmp_table_param.cleanup();
unknown's avatar
unknown committed
2938
  DBUG_VOID_RETURN;
unknown's avatar
unknown committed
2939 2940 2941 2942
}


/*****************************************************************************
2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955
  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
2956 2957 2958 2959 2960 2961
*****************************************************************************/

static bool
eq_ref_table(JOIN *join, ORDER *start_order, JOIN_TAB *tab)
{
  if (tab->cached_eq_ref_table)			// If cached
unknown's avatar
unknown committed
2962
    return tab->eq_ref_table;
unknown's avatar
unknown committed
2963 2964
  tab->cached_eq_ref_table=1;
  if (tab->type == JT_CONST)			// We can skip const tables
unknown's avatar
unknown committed
2965
    return (tab->eq_ref_table=1);		/* purecov: inspected */
unknown's avatar
unknown committed
2966
  if (tab->type != JT_EQ_REF)
unknown's avatar
unknown committed
2967
    return (tab->eq_ref_table=0);		// We must use this
unknown's avatar
unknown committed
2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979
  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)
      {
2980
	if ((*ref_item)->eq(order->item[0],0))
unknown's avatar
unknown committed
2981 2982 2983 2984 2985
	  break;
      }
      if (order)
      {
	found++;
unknown's avatar
unknown committed
2986
	DBUG_ASSERT(!(order->used & map));
unknown's avatar
unknown committed
2987 2988 2989 2990
	order->used|=map;
	continue;				// Used in ORDER BY
      }
      if (!only_eq_ref_tables(join,start_order, (*ref_item)->used_tables()))
unknown's avatar
unknown committed
2991
	return (tab->eq_ref_table=0);
unknown's avatar
unknown committed
2992 2993 2994
    }
  }
  /* Check that there was no reference to table before sort order */
2995
  for (; found && start_order ; start_order=start_order->next)
unknown's avatar
unknown committed
2996 2997 2998 2999 3000 3001 3002
  {
    if (start_order->used & map)
    {
      found--;
      continue;
    }
    if (start_order->depend_map & map)
unknown's avatar
unknown committed
3003
      return (tab->eq_ref_table=0);
unknown's avatar
unknown committed
3004
  }
unknown's avatar
unknown committed
3005
  return tab->eq_ref_table=1;
unknown's avatar
unknown committed
3006 3007 3008 3009 3010 3011 3012
}


static bool
only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables)
{
  if (specialflag &  SPECIAL_SAFE_MODE)
unknown's avatar
unknown committed
3013
    return 0;			// skip this optimize /* purecov: inspected */
unknown's avatar
unknown committed
3014 3015 3016
  for (JOIN_TAB **tab=join->map2table ; tables ; tab++, tables>>=1)
  {
    if (tables & 1 && !eq_ref_table(join, order, *tab))
unknown's avatar
unknown committed
3017
      return 0;
unknown's avatar
unknown committed
3018
  }
unknown's avatar
unknown committed
3019
  return 1;
unknown's avatar
unknown committed
3020 3021 3022 3023 3024 3025 3026 3027 3028
}


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

3029
  for (; join_tab != end ; join_tab++)
unknown's avatar
unknown committed
3030 3031 3032 3033 3034 3035 3036 3037
  {
    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();
    ref->depend_map=depend_map;
3038
    for (JOIN_TAB **tab=join->map2table;
unknown's avatar
unknown committed
3039
	 depend_map ;
3040
	 tab++,depend_map>>=1 )
unknown's avatar
unknown committed
3041 3042
    {
      if (depend_map & 1)
3043
	ref->depend_map|=(*tab)->ref.depend_map;
unknown's avatar
unknown committed
3044 3045 3046 3047 3048 3049 3050 3051 3052
    }
  }
}


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

static void update_depend_map(JOIN *join, ORDER *order)
{
3053
  for (; order ; order=order->next)
unknown's avatar
unknown committed
3054 3055 3056 3057 3058 3059
  {
    table_map depend_map;
    order->item[0]->update_used_tables();
    order->depend_map=depend_map=order->item[0]->used_tables();
    if (!(order->depend_map & RAND_TABLE_BIT))	// Not item_sum() or RAND()
    {
3060
      for (JOIN_TAB **tab=join->map2table;
unknown's avatar
unknown committed
3061
	   depend_map ;
3062
	   tab++, depend_map>>=1)
unknown's avatar
unknown committed
3063 3064
      {
	if (depend_map & 1)
3065
	  order->depend_map|=(*tab)->ref.depend_map;
unknown's avatar
unknown committed
3066 3067 3068 3069 3070 3071 3072
      }
    }
  }
}


/*
unknown's avatar
unknown committed
3073 3074
  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
3075 3076 3077 3078 3079
*/

static ORDER *
remove_const(JOIN *join,ORDER *first_order, COND *cond, bool *simple_order)
{
unknown's avatar
unknown committed
3080
  if (join->tables == join->const_tables)
unknown's avatar
unknown committed
3081 3082
    return 0;					// No need to sort
  DBUG_ENTER("remove_const");
unknown's avatar
unknown committed
3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100
  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
3101
      continue;					// skip const item
unknown's avatar
unknown committed
3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135
    }
    else
    {
      if (order_tables & RAND_TABLE_BIT)
	*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)))
	{
	  if (only_eq_ref_tables(join,first_order,ref))
	  {
	    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);
}

3136

unknown's avatar
unknown committed
3137
static int
3138 3139 3140
return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
		 List<Item> &fields, bool send_row, uint select_options,
		 const char *info, Item *having, Procedure *procedure)
unknown's avatar
unknown committed
3141 3142 3143 3144
{
  DBUG_ENTER("return_zero_rows");

  if (select_options & SELECT_DESCRIBE)
3145 3146
  {
    describe_info(join, info);
unknown's avatar
unknown committed
3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157
    DBUG_RETURN(0);
  }
  if (procedure)
  {
    if (result->prepare(fields))		// This hasn't been done yet
      DBUG_RETURN(-1);
  }
  if (send_row)
  {
    for (TABLE_LIST *table=tables; table ; table=table->next)
      mark_as_null_row(table->table);		// All fields are NULL
3158
    if (having && having->val_int() == 0)
unknown's avatar
unknown committed
3159 3160
      send_row=0;
  }
3161
  if (!(result->send_fields(fields,1)))
unknown's avatar
unknown committed
3162 3163
  {
    if (send_row)
unknown's avatar
unknown committed
3164 3165 3166 3167 3168
    {
      List_iterator_fast<Item> it(fields);
      Item *item;
      while ((item= it++))
	item->no_rows_in_result();
unknown's avatar
unknown committed
3169
      result->send_data(fields);
unknown's avatar
unknown committed
3170
    }
3171
    if (tables)				// Not from do_select()
3172 3173 3174 3175 3176
    {
      /* Close open cursors */
      for (TABLE_LIST *table=tables; table ; table=table->next)
	table->table->file->index_end();
    }
3177
    result->send_eof();				// Should be safe
unknown's avatar
unknown committed
3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189
  }
  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
}

/*****************************************************************************
3190 3191 3192 3193 3194 3195
  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
3196 3197 3198 3199
*****************************************************************************/

class COND_CMP :public ilink {
public:
unknown's avatar
unknown committed
3200
  static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
unknown's avatar
unknown committed
3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216
  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

/*
3217 3218
  change field = field to field = const for each found field = const in the
  and_level
unknown's avatar
unknown committed
3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233
*/

static void
change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father,
			 Item *cond, Item *field, Item *value)
{
  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++))
      change_cond_ref_to_const(save_list,and_level ? cond : item, item,
			       field, value);
unknown's avatar
unknown committed
3234
    return;
unknown's avatar
unknown committed
3235 3236
  }
  if (cond->eq_cmp_result() == Item::COND_OK)
unknown's avatar
unknown committed
3237
    return;					// Not a boolean function
unknown's avatar
unknown committed
3238 3239 3240 3241 3242 3243

  Item_bool_func2 *func=  (Item_bool_func2*) cond;
  Item *left_item=  func->arguments()[0];
  Item *right_item= func->arguments()[1];
  Item_func::Functype functype=  func->functype();

3244
  if (right_item->eq(field,0) && left_item != value)
unknown's avatar
unknown committed
3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262
  {
    Item *tmp=value->new_item();
    if (tmp)
    {
      func->arguments()[1] = tmp;
      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);
      }
      func->set_cmp_func(item_cmp_type(func->arguments()[0]->result_type(),
				       func->arguments()[1]->result_type()));
    }
  }
3263
  else if (left_item->eq(field,0) && right_item != value)
unknown's avatar
unknown committed
3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294
  {
    Item *tmp=value->new_item();
    if (tmp)
    {
      func->arguments()[0] = value = tmp;
      func->update_used_tables();
      if ((functype == Item_func::EQ_FUNC || functype == Item_func::EQUAL_FUNC)
	  && and_father != cond && !right_item->const_item())
      {
	func->arguments()[0] = func->arguments()[1]; // For easy check
	func->arguments()[1] = value;
	cond->marker=1;
	COND_CMP *tmp2;
	if ((tmp2=new COND_CMP(and_father,func)))
	  save_list->push_back(tmp2);
      }
      func->set_cmp_func(item_cmp_type(func->arguments()[0]->result_type(),
				       func->arguments()[1]->result_type()));
    }
  }
}


static void
propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level,
			 COND *cond)
{
  if (cond->type() == Item::COND_ITEM)
  {
    bool and_level= ((Item_cond*) cond)->functype() ==
      Item_func::COND_AND_FUNC;
unknown's avatar
unknown committed
3295
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322
    Item *item;
    I_List<COND_CMP> save;
    while ((item=li++))
    {
      propagate_cond_constants(&save,and_level ? cond : item, item);
    }
    if (and_level)
    {						// Handle other found items
      I_List_iterator<COND_CMP> cond_itr(save);
      COND_CMP *cond_cmp;
      while ((cond_cmp=cond_itr++))
	if (!cond_cmp->cmp_func->arguments()[0]->const_item())
	  change_cond_ref_to_const(&save,cond_cmp->and_level,
				   cond_cmp->and_level,
				   cond_cmp->cmp_func->arguments()[0],
				   cond_cmp->cmp_func->arguments()[1]);
    }
  }
  else if (and_level != cond && !cond->marker)		// In a AND group
  {
    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;
      bool left_const= func->arguments()[0]->const_item();
      bool right_const=func->arguments()[1]->const_item();
3323 3324 3325
      if (!(left_const && right_const) &&
	  (func->arguments()[0]->result_type() ==
	   (func->arguments()[1]->result_type())))
unknown's avatar
unknown committed
3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356
      {
	if (right_const)
	{
	  func->arguments()[1]=resolve_const_item(func->arguments()[1],
						  func->arguments()[0]);
	  func->update_used_tables();
	  change_cond_ref_to_const(save_list,and_level,and_level,
				   func->arguments()[0],
				   func->arguments()[1]);
	}
	else if (left_const)
	{
	  func->arguments()[0]=resolve_const_item(func->arguments()[0],
						  func->arguments()[1]);
	  func->update_used_tables();
	  change_cond_ref_to_const(save_list,and_level,and_level,
				   func->arguments()[1],
				   func->arguments()[0]);
	}
      }
    }
  }
}


static COND *
optimize_cond(COND *conds,Item::cond_result *cond_value)
{
  if (!conds)
  {
    *cond_value= Item::COND_TRUE;
unknown's avatar
unknown committed
3357
    return conds;
unknown's avatar
unknown committed
3358 3359 3360 3361 3362
  }
  /* change field = field to field = const for each found field = const */
  DBUG_EXECUTE("where",print_where(conds,"original"););
  propagate_cond_constants((I_List<COND_CMP> *) 0,conds,conds);
  /*
3363 3364
    Remove all instances of item == item
    Remove all and-levels where CONST item != CONST item
unknown's avatar
unknown committed
3365 3366 3367 3368
  */
  DBUG_EXECUTE("where",print_where(conds,"after const change"););
  conds=remove_eq_conds(conds,cond_value) ;
  DBUG_EXECUTE("info",print_where(conds,"after remove"););
unknown's avatar
unknown committed
3369
  return conds;
unknown's avatar
unknown committed
3370 3371 3372 3373
}


/*
3374 3375 3376 3377 3378
  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
3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389
*/

static COND *
remove_eq_conds(COND *cond,Item::cond_result *cond_value)
{
  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;
3390
    bool should_fix_fields=0;
unknown's avatar
unknown committed
3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409

    *cond_value=Item::COND_UNDEF;
    Item *item;
    while ((item=li++))
    {
      Item *new_item=remove_eq_conds(item,&tmp_cond_value);
      if (!new_item)
      {
#ifdef DELETE_ITEMS
	delete item;				// This may be shared
#endif
	li.remove();
      }
      else if (item != new_item)
      {
#ifdef DELETE_ITEMS
	delete item;				// This may be shared
#endif
	VOID(li.replace(new_item));
3410
	should_fix_fields=1;
unknown's avatar
unknown committed
3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422
      }
      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;
unknown's avatar
unknown committed
3423
	  return (COND*) 0;			// Always false
unknown's avatar
unknown committed
3424 3425 3426 3427 3428 3429
	}
	break;
      case Item::COND_TRUE:
	if (!and_level)
	{
	  *cond_value= tmp_cond_value;
unknown's avatar
unknown committed
3430
	  return (COND*) 0;			// Always true
unknown's avatar
unknown committed
3431 3432 3433 3434 3435 3436
	}
	break;
      case Item::COND_UNDEF:			// Impossible
	break; /* purecov: deadcode */
      }
    }
3437 3438 3439
    if (should_fix_fields)
      cond->fix_fields(current_thd,0);

unknown's avatar
unknown committed
3440 3441
    if (!((Item_cond*) cond)->argument_list()->elements ||
	*cond_value != Item::COND_OK)
unknown's avatar
unknown committed
3442
      return (COND*) 0;
unknown's avatar
unknown committed
3443 3444 3445 3446
    if (((Item_cond*) cond)->argument_list()->elements == 1)
    {						// Remove list
      item= ((Item_cond*) cond)->argument_list()->head();
      ((Item_cond*) cond)->argument_list()->empty();
unknown's avatar
unknown committed
3447
      return item;
unknown's avatar
unknown committed
3448 3449 3450 3451 3452 3453
    }
  }
  else if (cond->type() == Item::FUNC_ITEM &&
	   ((Item_func*) cond)->functype() == Item_func::ISNULL_FUNC)
  {
    /*
3454 3455 3456 3457 3458 3459 3460
      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
3461 3462 3463 3464
    */

    Item_func_isnull *func=(Item_func_isnull*) cond;
    Item **args= func->arguments();
3465
    THD *thd=current_thd;
unknown's avatar
unknown committed
3466 3467 3468 3469
    if (args[0]->type() == Item::FIELD_ITEM)
    {
      Field *field=((Item_field*) args[0])->field;
      if (field->flags & AUTO_INCREMENT_FLAG && !field->table->maybe_null &&
3470 3471
	  (thd->options & OPTION_AUTO_IS_NULL) &&
	  thd->insert_id())
unknown's avatar
unknown committed
3472
      {
unknown's avatar
unknown committed
3473
	query_cache_abort(&thd->net);
unknown's avatar
unknown committed
3474 3475 3476
	COND *new_cond;
	if ((new_cond= new Item_func_eq(args[0],
					new Item_int("last_insert_id()",
3477
						     thd->insert_id(),
unknown's avatar
unknown committed
3478 3479 3480
						     21))))
	{
	  cond=new_cond;
3481
	  cond->fix_fields(thd,0);
unknown's avatar
unknown committed
3482
	}
3483
	thd->insert_id(0);		// Clear for next request
unknown's avatar
unknown committed
3484 3485 3486 3487
      }
      /* fix to replace 'NULL' dates with '0' (shreeve@uci.edu) */
      else if (((field->type() == FIELD_TYPE_DATE) ||
		(field->type() == FIELD_TYPE_DATETIME)) &&
3488 3489
		(field->flags & NOT_NULL_FLAG) &&
	       !field->table->maybe_null)
unknown's avatar
unknown committed
3490 3491 3492 3493 3494
      {
	COND *new_cond;
	if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2))))
	{
	  cond=new_cond;
3495
	  cond->fix_fields(thd,0);
unknown's avatar
unknown committed
3496 3497 3498 3499 3500 3501 3502
	}
      }
    }
  }
  else if (cond->const_item())
  {
    *cond_value= eval_const_cond(cond) ? Item::COND_TRUE : Item::COND_FALSE;
unknown's avatar
unknown committed
3503
    return (COND*) 0;
unknown's avatar
unknown committed
3504 3505 3506 3507 3508
  }
  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];
3509
    if (left_item->eq(right_item,1))
unknown's avatar
unknown committed
3510 3511 3512
    {
      if (!left_item->maybe_null ||
	  ((Item_func*) cond)->functype() == Item_func::EQUAL_FUNC)
unknown's avatar
unknown committed
3513
	return (COND*) 0;			// Compare of identical items
unknown's avatar
unknown committed
3514 3515 3516
    }
  }
  *cond_value=Item::COND_OK;
unknown's avatar
unknown committed
3517
  return cond;					// Point at next and level
unknown's avatar
unknown committed
3518 3519 3520
}

/*
3521
  Return 1 if the item is a const value in all the WHERE clause
unknown's avatar
unknown committed
3522 3523 3524 3525 3526 3527 3528 3529 3530
*/

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
3531
    List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
unknown's avatar
unknown committed
3532 3533 3534 3535 3536 3537 3538
    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)
unknown's avatar
unknown committed
3539
	  return 1;
unknown's avatar
unknown committed
3540 3541
      }
      else if (!and_level)
unknown's avatar
unknown committed
3542
	return 0;
unknown's avatar
unknown committed
3543
    }
unknown's avatar
unknown committed
3544
    return and_level ? 0 : 1;
unknown's avatar
unknown committed
3545 3546 3547 3548 3549 3550
  }
  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)
unknown's avatar
unknown committed
3551
      return 0;
unknown's avatar
unknown committed
3552 3553
    Item *left_item=	((Item_func*) cond)->arguments()[0];
    Item *right_item= ((Item_func*) cond)->arguments()[1];
3554
    if (left_item->eq(comp_item,1))
unknown's avatar
unknown committed
3555 3556 3557 3558
    {
      if (right_item->const_item())
      {
	if (*const_item)
unknown's avatar
unknown committed
3559
	  return right_item->eq(*const_item, 1);
unknown's avatar
unknown committed
3560
	*const_item=right_item;
unknown's avatar
unknown committed
3561
	return 1;
unknown's avatar
unknown committed
3562 3563
      }
    }
3564
    else if (right_item->eq(comp_item,1))
unknown's avatar
unknown committed
3565 3566 3567 3568
    {
      if (left_item->const_item())
      {
	if (*const_item)
unknown's avatar
unknown committed
3569
	  return left_item->eq(*const_item, 1);
unknown's avatar
unknown committed
3570
	*const_item=left_item;
unknown's avatar
unknown committed
3571
	return 1;
unknown's avatar
unknown committed
3572 3573 3574
      }
    }
  }
unknown's avatar
unknown committed
3575
  return 0;
unknown's avatar
unknown committed
3576 3577 3578 3579
}


/****************************************************************************
unknown's avatar
unknown committed
3580
  Create internal temporary table
unknown's avatar
unknown committed
3581 3582
****************************************************************************/

unknown's avatar
unknown committed
3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607
/*
  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
    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
		       
  RETURN
    0			on error
    new_created field
*/

unknown's avatar
unknown committed
3608
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
unknown's avatar
unknown committed
3609
			Item ***copy_func, Field **from_field,
unknown's avatar
unknown committed
3610 3611 3612 3613 3614 3615 3616 3617 3618 3619
			bool group, bool modify_item)
{
  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)
unknown's avatar
unknown committed
3620 3621
	return new Field_string(sizeof(double)+sizeof(longlong),
				maybe_null, item->name,table,1);
unknown's avatar
unknown committed
3622
      else
unknown's avatar
unknown committed
3623 3624
	return new Field_double(item_sum->max_length,maybe_null,
				item->name, table, item_sum->decimals);
unknown's avatar
unknown committed
3625 3626
    case Item_sum::STD_FUNC:			/* Place for sum & count */
      if (group)
unknown's avatar
unknown committed
3627 3628
	return	new Field_string(sizeof(double)*2+sizeof(longlong),
				 maybe_null, item->name,table,1);
unknown's avatar
unknown committed
3629
      else
unknown's avatar
unknown committed
3630 3631
	return new Field_double(item_sum->max_length, maybe_null,
				item->name,table,item_sum->decimals);
unknown's avatar
unknown committed
3632
    case Item_sum::UNIQUE_USERS_FUNC:
unknown's avatar
unknown committed
3633
      return new Field_long(9,maybe_null,item->name,table,1);
unknown's avatar
unknown committed
3634 3635 3636
    default:
      switch (item_sum->result_type()) {
      case REAL_RESULT:
unknown's avatar
unknown committed
3637 3638
	return new Field_double(item_sum->max_length,maybe_null,
				item->name,table,item_sum->decimals);
unknown's avatar
unknown committed
3639
      case INT_RESULT:
unknown's avatar
unknown committed
3640 3641
	return new Field_longlong(item_sum->max_length,maybe_null,
				  item->name,table,item->unsigned_flag);
unknown's avatar
unknown committed
3642 3643
      case STRING_RESULT:
	if (item_sum->max_length > 255)
unknown's avatar
unknown committed
3644 3645 3646 3647
	  return  new Field_blob(item_sum->max_length,maybe_null,
				 item->name,table,item->binary);
	return	new Field_string(item_sum->max_length,maybe_null,
				 item->name,table,item->binary);
unknown's avatar
unknown committed
3648 3649
      }
    }
unknown's avatar
unknown committed
3650
    thd->fatal_error=1;
unknown's avatar
unknown committed
3651
    return 0;					// Error
unknown's avatar
unknown committed
3652 3653 3654 3655 3656 3657
  }
  case Item::FIELD_ITEM:
  {
    Field *org_field=((Item_field*) item)->field,*new_field;

    *from_field=org_field;
unknown's avatar
unknown committed
3658 3659
    // The following should always be true
    if ((new_field= org_field->new_field(&thd->mem_root,table)))
unknown's avatar
unknown committed
3660 3661 3662 3663 3664 3665 3666 3667
    {
      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
    }
unknown's avatar
unknown committed
3668
    return new_field;
unknown's avatar
unknown committed
3669 3670 3671 3672 3673 3674
  }
  case Item::FUNC_ITEM:
  case Item::COND_ITEM:
  case Item::FIELD_AVG_ITEM:
  case Item::FIELD_STD_ITEM:
    /* The following can only happen with 'CREATE TABLE ... SELECT' */
unknown's avatar
unknown committed
3675
  case Item::PROC_ITEM:
unknown's avatar
unknown committed
3676 3677 3678 3679
  case Item::INT_ITEM:
  case Item::REAL_ITEM:
  case Item::STRING_ITEM:
  case Item::REF_ITEM:
3680
  case Item::NULL_ITEM:
unknown's avatar
unknown committed
3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692
  {
    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,
3693
				   item->name,table, item->unsigned_flag);
unknown's avatar
unknown committed
3694 3695 3696 3697 3698 3699 3700 3701 3702 3703
      break;
    case STRING_RESULT:
      if (item->max_length > 255)
	new_field=  new Field_blob(item->max_length,maybe_null,
				   item->name,table,item->binary);
      else
	new_field= new Field_string(item->max_length,maybe_null,
				    item->name,table,item->binary);
      break;
    }
unknown's avatar
unknown committed
3704 3705
    if (copy_func && item->is_result_field())
      *((*copy_func)++) = item;			// Save for copy_funcs
unknown's avatar
unknown committed
3706
    if (modify_item)
unknown's avatar
unknown committed
3707
      item->set_result_field(new_field);
unknown's avatar
unknown committed
3708
    return new_field;
unknown's avatar
unknown committed
3709 3710
  }
  default:					// Dosen't have to be stored
unknown's avatar
unknown committed
3711
    return 0;
unknown's avatar
unknown committed
3712 3713 3714 3715
  }
}


unknown's avatar
unknown committed
3716 3717 3718 3719 3720 3721 3722
/*
  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
3723 3724 3725
TABLE *
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
		 ORDER *group, bool distinct, bool save_sum_fields,
3726
		 bool allow_distinct_limit, ulong select_options)
unknown's avatar
unknown committed
3727 3728 3729
{
  TABLE *table;
  uint	i,field_count,reclength,null_count,null_pack_length,
unknown's avatar
unknown committed
3730
        hidden_null_count, hidden_null_pack_length, hidden_field_count,
unknown's avatar
unknown committed
3731 3732
	blob_count,group_null_items;
  bool	using_unique_constraint=0;
unknown's avatar
unknown committed
3733
  bool  not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS);
unknown's avatar
unknown committed
3734 3735 3736
  char	*tmpname,path[FN_REFLEN];
  byte	*pos,*group_buff;
  uchar *null_flags;
3737
  Field **reg_field, **from_field, **blob_field;
unknown's avatar
unknown committed
3738 3739 3740
  Copy_field *copy=0;
  KEY *keyinfo;
  KEY_PART_INFO *key_part_info;
unknown's avatar
unknown committed
3741
  Item **copy_func;
unknown's avatar
unknown committed
3742
  MI_COLUMNDEF *recinfo;
3743
  uint temp_pool_slot=MY_BIT_NONE;
unknown's avatar
unknown committed
3744

unknown's avatar
unknown committed
3745
  DBUG_ENTER("create_tmp_table");
unknown's avatar
unknown committed
3746 3747 3748 3749
  DBUG_PRINT("enter",("distinct: %d  save_sum_fields: %d  allow_distinct_limit: %d  group: %d",
		      (int) distinct, (int) save_sum_fields,
		      (int) allow_distinct_limit,test(group)));

3750
  statistic_increment(created_tmp_tables, &LOCK_status);
3751

3752
  if (use_temp_pool)
unknown's avatar
unknown committed
3753
    temp_pool_slot = bitmap_set_next(&temp_pool);
3754 3755

  if (temp_pool_slot != MY_BIT_NONE) // we got a slot
3756
    sprintf(path, "%s%s_%lx_%i", mysql_tmpdir, tmp_file_prefix,
3757 3758
	    current_pid, temp_pool_slot);
  else // if we run out of slots or we are not using tempool
3759 3760 3761
    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
3762 3763 3764 3765 3766
  if (group)
  {
    if (!param->quick_group)
      group=0;					// Can't use group key
    else for (ORDER *tmp=group ; tmp ; tmp=tmp->next)
3767
    {
unknown's avatar
unknown committed
3768
      (*tmp->item)->marker=4;			// Store null in key
3769 3770 3771
      if ((*tmp->item)->max_length >= MAX_CHAR_WIDTH)
	using_unique_constraint=1;
    }
unknown's avatar
unknown committed
3772 3773
    if (param->group_length >= MAX_BLOB_WIDTH)
      using_unique_constraint=1;
unknown's avatar
unknown committed
3774 3775
    if (group)
      distinct=0;				// Can't use distinct
unknown's avatar
unknown committed
3776 3777 3778
  }

  field_count=param->field_count+param->func_count+param->sum_func_count;
unknown's avatar
unknown committed
3779
  hidden_field_count=param->hidden_field_count;
unknown's avatar
unknown committed
3780 3781
  if (!my_multi_malloc(MYF(MY_WME),
		       &table,sizeof(*table),
3782 3783 3784
		       &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
3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795
		       &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
3796
    bitmap_clear_bit(&temp_pool, temp_pool_slot);
3797
    DBUG_RETURN(NULL);				/* purecov: inspected */
unknown's avatar
unknown committed
3798 3799 3800
  }
  if (!(param->copy_field=copy=new Copy_field[field_count]))
  {
unknown's avatar
unknown committed
3801
    bitmap_clear_bit(&temp_pool, temp_pool_slot);
3802 3803
    my_free((gptr) table,MYF(0));		/* purecov: inspected */
    DBUG_RETURN(NULL);				/* purecov: inspected */
unknown's avatar
unknown committed
3804
  }
unknown's avatar
unknown committed
3805
  param->items_to_copy= copy_func;
unknown's avatar
unknown committed
3806 3807 3808 3809 3810 3811 3812
  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;
3813
  table->blob_field= (Field_blob**) blob_field;
unknown's avatar
unknown committed
3814
  table->real_name=table->path=tmpname;
3815 3816 3817 3818
  /*
    This must be "" as field may refer to it after tempory table is dropped
  */
  table->table_name= (char*) "";
unknown's avatar
unknown committed
3819 3820 3821 3822
  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
3823
  table->tmp_table= TMP_TABLE;
unknown's avatar
unknown committed
3824
  table->db_low_byte_first=1;			// True for HEAP and MyISAM
3825
  table->temp_pool_slot = temp_pool_slot;
3826
  table->copy_blobs= 1;
unknown's avatar
unknown committed
3827

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

unknown's avatar
unknown committed
3830 3831
  reclength=blob_count=null_count=hidden_null_count=group_null_items=0;
  param->using_indirect_summary_function=0;
unknown's avatar
unknown committed
3832

unknown's avatar
unknown committed
3833
  List_iterator_fast<Item> li(fields);
unknown's avatar
unknown committed
3834 3835
  Item *item;
  Field **tmp_from_field=from_field;
3836
  while ((item=li++))
unknown's avatar
unknown committed
3837 3838
  {
    Item::Type type=item->type();
unknown's avatar
unknown committed
3839
    if (not_all_columns)
unknown's avatar
unknown committed
3840
    {
unknown's avatar
unknown committed
3841 3842 3843 3844 3845 3846 3847 3848 3849 3850
      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;
      }
3851
      if (item->const_item() && (int) hidden_field_count <= 0)
3852
        continue; // We don't have to store this
unknown's avatar
unknown committed
3853
    }
unknown's avatar
unknown committed
3854 3855 3856 3857 3858 3859 3860 3861 3862
    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++)
      {
	Item *arg= ((Item_sum*) item)->args[i];
	if (!arg->const_item())
	{
	  Field *new_field=
unknown's avatar
unknown committed
3863 3864
	    create_tmp_field(thd, table,arg,arg->type(),&copy_func,
			     tmp_from_field, group != 0,not_all_columns);
unknown's avatar
unknown committed
3865 3866 3867 3868 3869 3870 3871 3872
	  if (!new_field)
	    goto err;					// Should be OOM
	  tmp_from_field++;
	  *(reg_field++)= new_field;
	  reclength+=new_field->pack_length();
	  if (!(new_field->flags & NOT_NULL_FLAG))
	    null_count++;
	  if (new_field->flags & BLOB_FLAG)
3873 3874
	  {
	    *blob_field++= new_field;
unknown's avatar
unknown committed
3875
	    blob_count++;
3876
	  }
unknown's avatar
unknown committed
3877 3878 3879 3880 3881 3882
	  ((Item_sum*) item)->args[i]= new Item_field(new_field);
	}
      }
    }
    else
    {
unknown's avatar
unknown committed
3883 3884 3885 3886 3887 3888 3889 3890 3891 3892
      /*
	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.
      */
unknown's avatar
unknown committed
3893
      Field *new_field=create_tmp_field(thd, table, item,type, &copy_func,
unknown's avatar
unknown committed
3894
					tmp_from_field, group != 0,
unknown's avatar
unknown committed
3895
					not_all_columns || group !=0);
unknown's avatar
unknown committed
3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908
      if (!new_field)
      {
	if (thd->fatal_error)
	  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)
3909 3910
      {
	*blob_field++= new_field;
unknown's avatar
unknown committed
3911
	blob_count++;
3912
      }
unknown's avatar
unknown committed
3913 3914 3915 3916 3917 3918 3919
      if (item->marker == 4 && item->maybe_null)
      {
	group_null_items++;
	new_field->flags|= GROUP_FLAG;
      }
      *(reg_field++) =new_field;
    }
unknown's avatar
unknown committed
3920 3921
    if (!--hidden_field_count)
      hidden_null_count=null_count;
unknown's avatar
unknown committed
3922
  }
3923
  DBUG_ASSERT(field_count >= (uint) (reg_field - table->field));
unknown's avatar
unknown committed
3924
  field_count= (uint) (reg_field - table->field);
3925
  *blob_field= 0;				// End marker
unknown's avatar
unknown committed
3926 3927

  /* If result table is small; use a heap */
3928
  if (blob_count || using_unique_constraint ||
unknown's avatar
unknown committed
3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947
      (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
3948 3949
  {
    /* We need to ensure that first byte is not 0 for the delete link */
3950
    if (param->hidden_field_count)
unknown's avatar
unknown committed
3951 3952 3953 3954 3955 3956 3957
      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
3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984
  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;
    if (!(table->record[0]= (byte *) my_malloc(alloc_length*3, MYF(MY_WME))))
      goto err;
    table->record[1]= table->record[0]+alloc_length;
    table->record[2]= table->record[1]+alloc_length;
  }
  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
  }
  null_count= (blob_count == 0) ? 1 : 0;
unknown's avatar
unknown committed
3985
  hidden_field_count=param->hidden_field_count;
unknown's avatar
unknown committed
3986 3987 3988 3989 3990 3991 3992 3993 3994 3995
  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)
      {
3996 3997 3998 3999
	/*
	  We have to reserve one byte here for NULL bits,
	  as this is updated by 'end_update()'
	*/
unknown's avatar
unknown committed
4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033
	*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
4034
      recinfo->type=FIELD_SKIP_ENDSPACE;
unknown's avatar
unknown committed
4035 4036
    else
      recinfo->type=FIELD_NORMAL;
unknown's avatar
unknown committed
4037 4038
    if (!--hidden_field_count)
      null_count=(null_count+7) & ~7;		// move to next byte
unknown's avatar
unknown committed
4039 4040
  }

unknown's avatar
unknown committed
4041
  param->copy_field_end=copy;
unknown's avatar
unknown committed
4042 4043 4044
  param->recinfo=recinfo;
  store_record(table,2);			// Make empty default record

4045
  if (thd->variables.tmp_table_size == ~(ulong) 0)		// No limit
4046 4047 4048
    table->max_rows= ~(ha_rows) 0;
  else
    table->max_rows=(((table->db_type == DB_TYPE_HEAP) ?
4049 4050 4051
		      min(thd->variables.tmp_table_size,
			  thd->variables.max_heap_table_size) :
		      thd->variables.tmp_table_size)/ table->reclength);
unknown's avatar
unknown committed
4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071
  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;
    for (; group ; group=group->next,key_part_info++)
    {
      Field *field=(*group->item)->tmp_table_field();
      bool maybe_null=(*group->item)->maybe_null;
4072
      key_part_info->null_bit=0;
unknown's avatar
unknown committed
4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083
      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
4084
	if (!(group->field=field->new_field(&thd->mem_root,table)))
unknown's avatar
unknown committed
4085 4086 4087 4088
	  goto err; /* purecov: inspected */
	if (maybe_null)
	{
	  /*
4089 4090 4091 4092
	    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
4093
	  */
4094 4095 4096 4097 4098
	  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);
4099
	  group_buff++;
unknown's avatar
unknown committed
4100 4101 4102 4103 4104 4105 4106 4107 4108
	}
	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
4109
  if (distinct)
unknown's avatar
unknown committed
4110
  {
unknown's avatar
unknown committed
4111 4112 4113 4114 4115 4116
    /*
      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.
    */
4117 4118
    DBUG_PRINT("info",("hidden_field_count: %d", param->hidden_field_count));

unknown's avatar
unknown committed
4119
    null_pack_length-=hidden_null_pack_length;
unknown's avatar
unknown committed
4120
    keyinfo->key_parts= ((field_count-param->hidden_field_count)+
4121
			 test(null_pack_length));
unknown's avatar
unknown committed
4122
    if (allow_distinct_limit)
unknown's avatar
unknown committed
4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140
    {
      set_if_smaller(table->max_rows,thd->select_limit);
      param->end_write_records=thd->select_limit;
    }
    else
      param->end_write_records= HA_POS_ERROR;
    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;
4141
    keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL;
unknown's avatar
unknown committed
4142 4143
    keyinfo->key_length=(uint16) reclength;
    keyinfo->name=(char*) "tmp";
unknown's avatar
unknown committed
4144
    if (null_pack_length)
unknown's avatar
unknown committed
4145
    {
4146
      key_part_info->null_bit=0;
unknown's avatar
unknown committed
4147 4148
      key_part_info->offset=hidden_null_pack_length;
      key_part_info->length=null_pack_length;
unknown's avatar
unknown committed
4149 4150 4151 4152 4153 4154 4155 4156 4157 4158
      key_part_info->field=new Field_string((char*) table->record[0],
					    (uint32) key_part_info->length,
					    (uchar*) 0,
					    (uint) 0,
					    Field::NONE,
					    NullS, table, (bool) 1);
      key_part_info->key_type=FIELDFLAG_BINARY;
      key_part_info->type=    HA_KEYTYPE_BINARY;
      key_part_info++;
    }
4159
    /* Create a distinct key over the columns we are going to return */
unknown's avatar
unknown committed
4160 4161
    for (i=param->hidden_field_count, reg_field=table->field + i ;
	 i < field_count;
unknown's avatar
unknown committed
4162 4163
	 i++, reg_field++, key_part_info++)
    {
4164
      key_part_info->null_bit=0;
unknown's avatar
unknown committed
4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182
      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;
    }
  }
  if (thd->fatal_error)				// If end of memory
    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;
  }
4183 4184
  /* Set table_name for easier debugging */
  table->table_name= base_name(tmpname);
unknown's avatar
unknown committed
4185 4186 4187 4188
  if (!open_tmp_table(table))
    DBUG_RETURN(table);

 err:
4189 4190 4191 4192 4193
  /*
    Hack to ensure that free_blobs() doesn't fail if blob_field is not yet
    complete
  */
  *table->blob_field= 0;
4194
  free_tmp_table(thd,table);                    /* purecov: inspected */
unknown's avatar
unknown committed
4195
  bitmap_clear_bit(&temp_pool, temp_pool_slot);
unknown's avatar
unknown committed
4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206
  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;
unknown's avatar
unknown committed
4207
    return(1);
unknown's avatar
unknown committed
4208 4209
  }
  (void) table->file->extra(HA_EXTRA_QUICK);		/* Faster */
unknown's avatar
unknown committed
4210
  return(0);
unknown's avatar
unknown committed
4211 4212 4213 4214
}


static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
4215
				    ulong options)
unknown's avatar
unknown committed
4216 4217 4218 4219 4220
{
  int error;
  MI_KEYDEF keydef;
  MI_UNIQUEDEF uniquedef;
  KEY *keyinfo=param->keyinfo;
unknown's avatar
unknown committed
4221

unknown's avatar
unknown committed
4222
  DBUG_ENTER("create_myisam_tmp_table");
unknown's avatar
unknown committed
4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261
  if (table->keys)
  {						// Get keys for ni_create
    bool using_unique_constraint=0;
    MI_KEYSEG *seg= (MI_KEYSEG*) sql_calloc(sizeof(*seg) *
					    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;
4262 4263 4264 4265
      seg->flag=     0;
      seg->language= MY_CHARSET_CURRENT;
      seg->length=   keyinfo->key_part[i].length;
      seg->start=    keyinfo->key_part[i].offset;
unknown's avatar
unknown committed
4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285
      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;
      }
4286
      if (!(field->flags & NOT_NULL_FLAG))
unknown's avatar
unknown committed
4287 4288 4289
      {
	seg->null_bit= field->null_bit;
	seg->null_pos= (uint) (field->null_ptr - (uchar*) table->record[0]);
4290 4291 4292 4293 4294 4295 4296
	/*
	  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
4297 4298 4299 4300 4301
      }
    }
  }
  MI_CREATE_INFO create_info;
  bzero((char*) &create_info,sizeof(create_info));
4302 4303
  if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
      OPTION_BIG_TABLES)
unknown's avatar
unknown committed
4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316
    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
4317
  statistic_increment(created_tmp_disk_tables, &LOCK_status);
unknown's avatar
unknown committed
4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333
  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";
4334
  free_blobs(entry);
unknown's avatar
unknown committed
4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346
  if (entry->db_stat && entry->file)
  {
    (void) entry->file->close();
    delete entry->file;
  }
  if (!(test_flags & TEST_KEEP_TMP_TABLES) || entry->db_type == DB_TYPE_HEAP)
    (void) ha_delete_table(entry->db_type,entry->real_name);
  /* free blobs */
  for (Field **ptr=entry->field ; *ptr ; ptr++)
    delete *ptr;
  my_free((gptr) entry->record[0],MYF(0));
  free_io_cache(entry);
4347

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

unknown's avatar
unknown committed
4350 4351 4352 4353 4354 4355 4356 4357 4358 4359
  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
4360 4361
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
4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381
{
  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,
4382
			      thd->lex.select_lex.options | thd->options))
unknown's avatar
unknown committed
4383 4384 4385 4386 4387
    goto err2;
  if (open_tmp_table(&new_table))
    goto err1;
  table->file->index_end();
  table->file->rnd_init();
4388 4389
  if (table->no_rows)
  {
4390 4391
    new_table.file->extra(HA_EXTRA_NO_ROWS);
    new_table.no_rows=1;
4392 4393
  }

unknown's avatar
unknown committed
4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415
  /* 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 */
  (void) table->file->rnd_end();
  (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);
4416 4417
  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
4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433
  DBUG_RETURN(0);

 err:
  DBUG_PRINT("error",("Got error: %d",write_err));
  table->file->print_error(error,MYF(0));	// Give table is full error
  (void) table->file->rnd_end();
  (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);
}


4434 4435 4436 4437 4438 4439
/****************************************************************************
  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
4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450

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

  join->procedure=procedure;
  /*
4451
    Tell the client how many fields there are in a row
unknown's avatar
unknown committed
4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469
  */
  if (!table)
    join->result->send_fields(*fields,1);
  else
  {
    VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
    empty_record(table);
  }
  join->tmp_table=table;			/* Save for easy recursion */
  join->fields= fields;

  /* Set up select_end */
  if (table)
  {
    if (table->group && join->tmp_table_param.sum_func_count)
    {
      if (table->keys)
      {
4470
	DBUG_PRINT("info",("Using end_update"));
unknown's avatar
unknown committed
4471 4472 4473 4474
	end_select=end_update;
	table->file->index_init(0);
      }
      else
4475 4476
      {
	DBUG_PRINT("info",("Using end_unique_update"));
unknown's avatar
unknown committed
4477
	end_select=end_unique_update;
4478
      }
unknown's avatar
unknown committed
4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515
    }
    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)
  {
    if (!(error=(*end_select)(join,join_tab,0)) || error == -3)
      error=(*end_select)(join,join_tab,1);
  }
  else
  {
    error=sub_select(join,join_tab,0);
    if (error >= 0)
      error=sub_select(join,join_tab,1);
    if (error == -3)
      error=0;					/* select_limit used */
  }
4516 4517

  /* Return 1 if error is sent;  -1 if error should be sent */
4518
  if (error < 0)
4519 4520 4521 4522
  {
    join->result->send_error(0,NullS);		/* purecov: inspected */
    error=1;					// Error sent
  }
4523
  else
unknown's avatar
unknown committed
4524
  {
4525 4526
    error=0;
    if (!table)					// If sending data to client
4527
    {
4528
      /*
4529 4530
	The following will unlock all cursors if the command wasn't an
	update command
4531
      */
4532 4533 4534
      join_free(join);
      if (join->result->send_eof())
	error= 1;				// Don't send error
4535
    }
unknown's avatar
unknown committed
4536 4537 4538 4539
    DBUG_PRINT("info",("%ld records output",join->send_records));
  }
  if (table)
  {
4540
    int tmp;
unknown's avatar
unknown committed
4541 4542 4543 4544 4545
    if ((tmp=table->file->extra(HA_EXTRA_NO_CACHE)))
    {
      my_errno=tmp;
      error= -1;
    }
unknown's avatar
unknown committed
4546
    if ((tmp=table->file->index_end()))
unknown's avatar
unknown committed
4547 4548 4549 4550
    {
      my_errno=tmp;
      error= -1;
    }
4551
    if (error == -1)
unknown's avatar
unknown committed
4552 4553
      table->file->print_error(my_errno,MYF(0));
  }
4554
  DBUG_RETURN(error);
unknown's avatar
unknown committed
4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565
}


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)
unknown's avatar
unknown committed
4566 4567
      return error; /* purecov: inspected */
    return sub_select(join,join_tab,end_of_records);
unknown's avatar
unknown committed
4568
  }
4569 4570 4571
  if (join->thd->killed)		// If aborted by user
  {
    my_error(ER_SERVER_SHUTDOWN,MYF(0)); /* purecov: inspected */
unknown's avatar
unknown committed
4572
    return -2;				 /* purecov: inspected */
4573
  }
unknown's avatar
unknown committed
4574 4575 4576
  if (join_tab->use_quick != 2 || test_if_quick_select(join_tab) <= 0)
  {
    if (!store_record_in_cache(&join_tab->cache))
unknown's avatar
unknown committed
4577 4578
      return 0;					// There is more room in cache
    return flush_cached_records(join,join_tab,FALSE);
unknown's avatar
unknown committed
4579 4580
  }
  if ((error=flush_cached_records(join,join_tab,TRUE)) < 0)
unknown's avatar
unknown committed
4581 4582
    return error; /* purecov: inspected */
  return sub_select(join,join_tab,end_of_records); /* Use ordinary select */
unknown's avatar
unknown committed
4583 4584 4585 4586 4587 4588 4589 4590 4591
}


static int
sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
{

  join_tab->table->null_row=0;
  if (end_of_records)
unknown's avatar
unknown committed
4592
    return (*join_tab->next_select)(join,join_tab+1,end_of_records);
unknown's avatar
unknown committed
4593 4594 4595 4596 4597 4598 4599 4600

  /* Cache variables for faster loop */
  int error;
  bool found=0;
  COND *on_expr=join_tab->on_expr, *select_cond=join_tab->select_cond;

  if (!(error=(*join_tab->read_first_record)(join_tab)))
  {
unknown's avatar
unknown committed
4601 4602 4603
    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
4604 4605 4606 4607 4608 4609 4610
    READ_RECORD *info= &join_tab->read_record;

    do
    {
      if (join->thd->killed)			// Aborted by user
      {
	my_error(ER_SERVER_SHUTDOWN,MYF(0));	/* purecov: inspected */
unknown's avatar
unknown committed
4611
	return -2;				/* purecov: inspected */
unknown's avatar
unknown committed
4612
      }
4613
      join->examined_rows++;
unknown's avatar
unknown committed
4614 4615 4616 4617 4618 4619 4620
      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())
	{
4621
	  if ((error=(*join_tab->next_select)(join,join_tab+1,0)) < 0)
unknown's avatar
unknown committed
4622
	    return error;
unknown's avatar
unknown committed
4623 4624 4625 4626 4627
	  /*
	    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
4628
	  if (not_used_in_distinct && found_records != join->found_records)
unknown's avatar
unknown committed
4629
	    return 0;
unknown's avatar
unknown committed
4630
	}
unknown's avatar
unknown committed
4631 4632
	else
	  info->file->unlock_row();
unknown's avatar
unknown committed
4633 4634 4635
      }
    } while (!(error=info->read_record(info)));
  }
4636
  if (error > 0)				// Fatal error
unknown's avatar
unknown committed
4637
    return -1;
unknown's avatar
unknown committed
4638 4639 4640 4641 4642 4643 4644

  if (!found && on_expr)
  {						// OUTER JOIN
    restore_record(join_tab->table,2);		// Make empty record
    mark_as_null_row(join_tab->table);		// For group by without error
    if (!select_cond || select_cond->val_int())
    {
4645
      if ((error=(*join_tab->next_select)(join,join_tab+1,0)) < 0)
unknown's avatar
unknown committed
4646
	return error;				/* purecov: inspected */
unknown's avatar
unknown committed
4647 4648
    }
  }
unknown's avatar
unknown committed
4649
  return 0;
unknown's avatar
unknown committed
4650 4651 4652 4653 4654 4655 4656 4657 4658 4659
}


static int
flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skipp_last)
{
  int error;
  READ_RECORD *info;

  if (!join_tab->cache.records)
unknown's avatar
unknown committed
4660
    return 0;				/* Nothing to do */
unknown's avatar
unknown committed
4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675
  if (skipp_last)
    (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)))
  {
    reset_cache(&join_tab->cache);
    join_tab->cache.records=0; join_tab->cache.ptr_record= (uint) ~0;
unknown's avatar
unknown committed
4676
    return -error;			/* No records or error */
unknown's avatar
unknown committed
4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690
  }

  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 */
unknown's avatar
unknown committed
4691
      return -2;				// Aborted by user /* purecov: inspected */
unknown's avatar
unknown committed
4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703
    }
    SQL_SELECT *select=join_tab->select;
    if (!error && (!join_tab->cache.select ||
		   !join_tab->cache.select->skipp_record()))
    {
      uint i;
      reset_cache(&join_tab->cache);
      for (i=(join_tab->cache.records- (skipp_last ? 1 : 0)) ; i-- > 0 ;)
      {
	read_cached_record(join_tab);
	if (!select || !select->skipp_record())
	  if ((error=(join_tab->next_select)(join,join_tab+1,0)) < 0)
unknown's avatar
unknown committed
4704
	    return error; /* purecov: inspected */
unknown's avatar
unknown committed
4705 4706 4707 4708 4709 4710 4711 4712 4713
      }
    }
  } while (!(error=info->read_record(info)));

  if (skipp_last)
    read_cached_record(join_tab);		// Restore current record
  reset_cache(&join_tab->cache);
  join_tab->cache.records=0; join_tab->cache.ptr_record= (uint) ~0;
  if (error > 0)				// Fatal error
unknown's avatar
unknown committed
4714
    return -1;					/* purecov: inspected */
unknown's avatar
unknown committed
4715 4716
  for (JOIN_TAB *tmp2=join->join_tab; tmp2 != join_tab ; tmp2++)
    tmp2->table->status=tmp2->status;
unknown's avatar
unknown committed
4717
  return 0;
unknown's avatar
unknown committed
4718 4719 4720 4721
}


/*****************************************************************************
4722 4723
  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
4724 4725
*****************************************************************************/
static int
4726
join_read_const_table(JOIN_TAB *tab, POSITION *pos)
unknown's avatar
unknown committed
4727 4728
{
  int error;
4729 4730 4731 4732 4733 4734 4735
  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
4736
  {
4737 4738 4739 4740 4741 4742 4743
    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
4744
    }
4745 4746 4747 4748
  }
  else
  {
    if ((error=join_read_const(tab)))
unknown's avatar
unknown committed
4749
    {
4750 4751 4752 4753 4754
      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
4755 4756
    }
  }
4757 4758 4759 4760 4761 4762 4763
  if (tab->on_expr && !table->null_row)
  {
    if ((table->null_row= test(tab->on_expr->val_int() == 0)))
      empty_record(table);
    }
  if (!table->null_row)
    table->maybe_null=0;
unknown's avatar
unknown committed
4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774
  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
  {
4775 4776
    if ((error=table->file->read_first_row(table->record[0],
					   table->primary_key)))
unknown's avatar
unknown committed
4777 4778 4779 4780
    {
      if (error != HA_ERR_END_OF_FILE)
      {
	table->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
4781
	return 1;
unknown's avatar
unknown committed
4782 4783 4784
      }
      table->null_row=1;			// This is ok.
      empty_record(table);			// Make empty record
unknown's avatar
unknown committed
4785
      return -1;
unknown's avatar
unknown committed
4786 4787 4788 4789 4790 4791
    }
    store_record(table,1);
  }
  else if (!table->status)			// Only happens with left join
    restore_record(table,1);			// restore old record
  table->null_row=0;
unknown's avatar
unknown committed
4792
  return table->status ? -1 : 0;
unknown's avatar
unknown committed
4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816
}


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)
    {
      table->null_row=1;
      empty_record(table);
      if (error != HA_ERR_KEY_NOT_FOUND)
      {
unknown's avatar
unknown committed
4817 4818 4819 4820
	/* 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("read_const: Got error %d when reading table %s",
unknown's avatar
unknown committed
4821
			error, table->path);
unknown's avatar
unknown committed
4822
	table->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
4823
	return 1;
unknown's avatar
unknown committed
4824
      }
unknown's avatar
unknown committed
4825
      return -1;
unknown's avatar
unknown committed
4826 4827 4828
    }
    store_record(table,1);
  }
unknown's avatar
unknown committed
4829 4830 4831
  else if (!(table->status & ~STATUS_NULL_ROW))	// Only happens with left join
  {
    table->status=0;
unknown's avatar
unknown committed
4832
    restore_record(table,1);			// restore old record
unknown's avatar
unknown committed
4833
  }
unknown's avatar
unknown committed
4834
  table->null_row=0;
unknown's avatar
unknown committed
4835
  return table->status ? -1 : 0;
unknown's avatar
unknown committed
4836 4837 4838 4839 4840 4841 4842 4843 4844 4845
}


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

  if (cmp_buffer_with_ref(tab) ||
4846
      (table->status & (STATUS_GARBAGE | STATUS_NO_PARENT | STATUS_NULL_ROW)))
unknown's avatar
unknown committed
4847 4848 4849 4850
  {
    if (tab->ref.key_err)
    {
      table->status=STATUS_NOT_FOUND;
unknown's avatar
unknown committed
4851
      return -1;
unknown's avatar
unknown committed
4852 4853 4854 4855 4856 4857 4858
    }
    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)
    {
      sql_print_error("read_key: Got error %d when reading table '%s'",error,
unknown's avatar
unknown committed
4859
		      table->path);
unknown's avatar
unknown committed
4860
      table->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
4861
      return 1;
unknown's avatar
unknown committed
4862 4863
    }
  }
4864
  table->null_row=0;
unknown's avatar
unknown committed
4865
  return table->status ? -1 : 0;
unknown's avatar
unknown committed
4866 4867 4868 4869 4870 4871 4872 4873 4874 4875
}


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

  if (cp_buffer_from_ref(&tab->ref))
unknown's avatar
unknown committed
4876
    return -1;
unknown's avatar
unknown committed
4877 4878 4879 4880 4881 4882
  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)
    {
unknown's avatar
unknown committed
4883 4884
      if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
	sql_print_error("read_const: Got error %d when reading table %s",error,
unknown's avatar
unknown committed
4885
		      table->path);
unknown's avatar
unknown committed
4886
      table->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
4887
      return 1;
unknown's avatar
unknown committed
4888
    }
unknown's avatar
unknown committed
4889
    return -1; /* purecov: inspected */
unknown's avatar
unknown committed
4890
  }
unknown's avatar
unknown committed
4891
  return 0;
unknown's avatar
unknown committed
4892 4893
}

4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905
/*
  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;

  if (cp_buffer_from_ref(&tab->ref))
unknown's avatar
unknown committed
4906
    return -1;
4907 4908 4909 4910 4911 4912
  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)
    {
unknown's avatar
unknown committed
4913 4914
      if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
	sql_print_error("read_const: Got error %d when reading table %s",error,
4915 4916
		      table->path);
      table->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
4917
      return 1;
4918
    }
unknown's avatar
unknown committed
4919
    return -1; /* purecov: inspected */
4920
  }
unknown's avatar
unknown committed
4921
  return 0;
4922 4923
}

unknown's avatar
unknown committed
4924 4925 4926 4927 4928

	/* ARGSUSED */
static int
join_no_more_records(READ_RECORD *info __attribute__((unused)))
{
unknown's avatar
unknown committed
4929
  return -1;
unknown's avatar
unknown committed
4930 4931 4932 4933
}


static int
4934
join_read_next_same(READ_RECORD *info)
unknown's avatar
unknown committed
4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945
{
  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)
    {
unknown's avatar
unknown committed
4946 4947
      if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
	sql_print_error("read_next: Got error %d when reading table %s",error,
unknown's avatar
unknown committed
4948
		      table->path);
unknown's avatar
unknown committed
4949
      table->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
4950
      return 1;
unknown's avatar
unknown committed
4951 4952
    }
    table->status= STATUS_GARBAGE;
unknown's avatar
unknown committed
4953
    return -1;
unknown's avatar
unknown committed
4954
  }
unknown's avatar
unknown committed
4955
  return 0;
unknown's avatar
unknown committed
4956 4957
}

4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968
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])))
  {
    if (error != HA_ERR_END_OF_FILE)
    {
unknown's avatar
unknown committed
4969 4970
      if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
	sql_print_error("read_next: Got error %d when reading table %s",error,
4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984
		      table->path);
      table->file->print_error(error,MYF(0));
      error= 1;
    }
    else
    {
      table->status= STATUS_GARBAGE;
      error= -1;
    }
  }
  else if (key_cmp(table, tab->ref.key_buff, tab->ref.key,
		   tab->ref.key_length))
  {
    table->status=STATUS_NOT_FOUND;
4985
    error= -1;
4986
  }
unknown's avatar
unknown committed
4987
  return error;
4988 4989
}

unknown's avatar
unknown committed
4990 4991 4992 4993 4994

static int
join_init_quick_read_record(JOIN_TAB *tab)
{
  if (test_if_quick_select(tab) == -1)
unknown's avatar
unknown committed
4995 4996
    return -1;					/* No possible records */
  return join_init_read_record(tab);
unknown's avatar
unknown committed
4997 4998 4999 5000 5001 5002 5003 5004
}


static int
test_if_quick_select(JOIN_TAB *tab)
{
  delete tab->select->quick;
  tab->select->quick=0;
unknown's avatar
unknown committed
5005
  return tab->select->test_quick_select(tab->keys,(table_map) 0,HA_POS_ERROR);
unknown's avatar
unknown committed
5006 5007 5008 5009 5010 5011 5012 5013
}


static int
join_init_read_record(JOIN_TAB *tab)
{
  if (tab->select && tab->select->quick)
    tab->select->quick->reset();
5014 5015
  init_read_record(&tab->read_record, tab->join->thd, tab->table,
		   tab->select,1,1);
unknown's avatar
unknown committed
5016
  return (*tab->read_record.read_record)(&tab->read_record);
unknown's avatar
unknown committed
5017 5018 5019
}

static int
5020
join_read_first(JOIN_TAB *tab)
unknown's avatar
unknown committed
5021 5022 5023
{
  int error;
  TABLE *table=tab->table;
unknown's avatar
unknown committed
5024 5025
  if (!table->key_read && (table->used_keys & ((key_map) 1 << tab->index)) &&
      !table->no_keyread)
unknown's avatar
unknown committed
5026 5027 5028 5029 5030
  {
    table->key_read=1;
    table->file->extra(HA_EXTRA_KEYREAD);
  }
  tab->table->status=0;
5031
  tab->read_record.read_record=join_read_next;
unknown's avatar
unknown committed
5032 5033 5034 5035 5036 5037 5038 5039 5040
  tab->read_record.table=table;
  tab->read_record.file=table->file;
  tab->read_record.index=tab->index;
  tab->read_record.record=table->record[0];
  error=tab->table->file->index_first(tab->table->record[0]);
  if (error)
  {
    if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
    {
unknown's avatar
unknown committed
5041 5042
      if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
	sql_print_error("read_first_with_key: Got error %d when reading table",
unknown's avatar
unknown committed
5043
		      error);
unknown's avatar
unknown committed
5044
      table->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
5045
      return 1;
unknown's avatar
unknown committed
5046
    }
unknown's avatar
unknown committed
5047
    return -1;
unknown's avatar
unknown committed
5048
  }
unknown's avatar
unknown committed
5049
  return 0;
unknown's avatar
unknown committed
5050 5051
}

5052

unknown's avatar
unknown committed
5053
static int
5054
join_read_next(READ_RECORD *info)
unknown's avatar
unknown committed
5055 5056 5057 5058 5059 5060
{
  int error=info->file->index_next(info->record);
  if (error)
  {
    if (error != HA_ERR_END_OF_FILE)
    {
unknown's avatar
unknown committed
5061 5062 5063
      if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
	sql_print_error(
		    "read_next_with_key: Got error %d when reading table %s",
unknown's avatar
unknown committed
5064
		      error, info->table->path);
unknown's avatar
unknown committed
5065
      info->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
5066
      return 1;
unknown's avatar
unknown committed
5067
    }
unknown's avatar
unknown committed
5068
    return -1;
unknown's avatar
unknown committed
5069
  }
unknown's avatar
unknown committed
5070
  return 0;
unknown's avatar
unknown committed
5071 5072 5073
}

static int
5074
join_read_last(JOIN_TAB *tab)
unknown's avatar
unknown committed
5075 5076 5077
{
  TABLE *table=tab->table;
  int error;
5078 5079
  if (!table->key_read && (table->used_keys & ((key_map) 1 << tab->index)) &&
      !table->no_keyread)
unknown's avatar
unknown committed
5080 5081 5082 5083 5084
  {
    table->key_read=1;
    table->file->extra(HA_EXTRA_KEYREAD);
  }
  tab->table->status=0;
5085
  tab->read_record.read_record=join_read_prev;
unknown's avatar
unknown committed
5086 5087 5088 5089 5090 5091 5092 5093 5094
  tab->read_record.table=table;
  tab->read_record.file=table->file;
  tab->read_record.index=tab->index;
  tab->read_record.record=table->record[0];
  error=tab->table->file->index_last(tab->table->record[0]);
  if (error)
  {
    if (error != HA_ERR_END_OF_FILE)
    {
unknown's avatar
unknown committed
5095 5096
      if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
	sql_print_error("read_last_with_key: Got error %d when reading table",
unknown's avatar
unknown committed
5097
		      error, table->path);
unknown's avatar
unknown committed
5098
      table->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
5099
      return 1;
unknown's avatar
unknown committed
5100
    }
unknown's avatar
unknown committed
5101
    return -1;
unknown's avatar
unknown committed
5102
  }
unknown's avatar
unknown committed
5103
  return 0;
unknown's avatar
unknown committed
5104 5105
}

5106

unknown's avatar
unknown committed
5107
static int
5108
join_read_prev(READ_RECORD *info)
unknown's avatar
unknown committed
5109 5110 5111 5112 5113 5114
{
  int error=info->file->index_prev(info->record);
  if (error)
  {
    if (error != HA_ERR_END_OF_FILE)
    {
unknown's avatar
unknown committed
5115 5116 5117
      if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
	sql_print_error(
		  "read_prev_with_key: Got error %d when reading table: %s",
unknown's avatar
unknown committed
5118
		      error,info->table->path);
unknown's avatar
unknown committed
5119
      info->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
5120
      return 1;
unknown's avatar
unknown committed
5121
    }
unknown's avatar
unknown committed
5122
    return -1;
unknown's avatar
unknown committed
5123
  }
unknown's avatar
unknown committed
5124
  return 0;
unknown's avatar
unknown committed
5125 5126
}

5127

unknown's avatar
unknown committed
5128 5129 5130 5131 5132 5133
static int
join_ft_read_first(JOIN_TAB *tab)
{
  int error;
  TABLE *table= tab->table;

unknown's avatar
unknown committed
5134
#if NOT_USED_YET
unknown's avatar
unknown committed
5135
  if (cp_buffer_from_ref(&tab->ref))       // as ft-key doesn't use store_key's
unknown's avatar
unknown committed
5136
    return -1;                             // see also FT_SELECT::init()
unknown's avatar
unknown committed
5137
#endif
5138
  table->file->ft_init();
unknown's avatar
unknown committed
5139 5140 5141 5142 5143 5144

  error=table->file->ft_read(table->record[0]);
  if (error)
  {
    if (error != HA_ERR_END_OF_FILE)
    {
unknown's avatar
unknown committed
5145 5146
      if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
	sql_print_error("ft_read_first: Got error %d when reading table %s",
unknown's avatar
unknown committed
5147
                      error, table->path);
unknown's avatar
unknown committed
5148
      table->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
5149
      return 1;
unknown's avatar
unknown committed
5150
    }
unknown's avatar
unknown committed
5151
    return -1;
unknown's avatar
unknown committed
5152
  }
unknown's avatar
unknown committed
5153
  return 0;
unknown's avatar
unknown committed
5154 5155 5156 5157 5158 5159 5160 5161 5162 5163
}

static int
join_ft_read_next(READ_RECORD *info)
{
  int error=info->file->ft_read(info->table->record[0]);
  if (error)
  {
    if (error != HA_ERR_END_OF_FILE)
    {
unknown's avatar
unknown committed
5164 5165
      if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
	sql_print_error("ft_read_next: Got error %d when reading table %s",
unknown's avatar
unknown committed
5166
                      error, info->table->path);
unknown's avatar
unknown committed
5167
      info->file->print_error(error,MYF(0));
unknown's avatar
unknown committed
5168
      return 1;
unknown's avatar
unknown committed
5169
    }
unknown's avatar
unknown committed
5170
    return -1;
unknown's avatar
unknown committed
5171
  }
unknown's avatar
unknown committed
5172
  return 0;
unknown's avatar
unknown committed
5173 5174 5175 5176
}


/*****************************************************************************
5177 5178 5179
  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
5180 5181
*****************************************************************************/

5182
/* ARGSUSED */
unknown's avatar
unknown committed
5183 5184 5185 5186 5187 5188 5189 5190
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;
5191
    if (join->having && join->having->val_int() == 0)
unknown's avatar
unknown committed
5192
      DBUG_RETURN(0);				// Didn't match having
5193
    error=0;
unknown's avatar
unknown committed
5194 5195
    if (join->procedure)
      error=join->procedure->send_row(*join->fields);
5196
    else if (join->do_send_rows)
unknown's avatar
unknown committed
5197 5198 5199
      error=join->result->send_data(*join->fields);
    if (error)
      DBUG_RETURN(-1); /* purecov: inspected */
unknown's avatar
unknown committed
5200 5201
    if (++join->send_records >= join->thd->select_limit &&
	join->do_send_rows)
5202 5203 5204
    {
      if (join->select_options & OPTION_FOUND_ROWS)
      {
5205
	JOIN_TAB *jt=join->join_tab;
5206
	if ((join->tables == 1) && !join->tmp_table && !join->sort_and_group
5207
	    && !join->send_group_parts && !join->having && !jt->select_cond &&
5208
	    !(jt->select && jt->select->quick) &&
5209
	    !(jt->table->file->table_flags() & HA_NOT_EXACT_COUNT))
5210
	{
5211
	  /* Join over all rows in table;  Return number of found rows */
5212 5213
	  TABLE *table=jt->table;

5214
	  join->select_options ^= OPTION_FOUND_ROWS;
5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225
	  if (table->record_pointers ||
	      (table->io_cache && my_b_inited(table->io_cache)))
	  {
	    /* Using filesort */
	    join->send_records= table->found_records;
	  }
	  else
	  {
	    table->file->info(HA_STATUS_VARIABLE);
	    join->send_records = table->file->records;
	  }
5226 5227 5228 5229 5230 5231 5232
	}
	else 
	{
	  join->do_send_rows=0;
	  join->thd->select_limit = HA_POS_ERROR;
	  DBUG_RETURN(0);
	}
5233
      }
unknown's avatar
unknown committed
5234
      DBUG_RETURN(-3);				// Abort nicely
5235
    }
unknown's avatar
unknown committed
5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262
  }
  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)
      {
5263
	int error=0;
unknown's avatar
unknown committed
5264 5265
	if (join->procedure)
	{
5266
	  if (join->having && join->having->val_int() == 0)
unknown's avatar
unknown committed
5267
	    error= -1;				// Didn't satisfy having
5268
 	  else if (join->do_send_rows)
unknown's avatar
unknown committed
5269 5270 5271 5272 5273 5274 5275
	    error=join->procedure->send_row(*join->fields) ? 1 : 0;
	  if (end_of_records && join->procedure->end_of_records())
	    error= 1;				// Fatal error
	}
	else
	{
	  if (!join->first_record)
5276 5277
	  {
	    /* No matching rows for group function */
unknown's avatar
unknown committed
5278
	    clear_tables(join);
5279 5280
	    copy_fields(&join->tmp_table_param);
	  }
5281
	  if (join->having && join->having->val_int() == 0)
unknown's avatar
unknown committed
5282
	    error= -1;				// Didn't satisfy having
5283
	  else if (join->do_send_rows)
unknown's avatar
unknown committed
5284 5285 5286 5287
	    error=join->result->send_data(*join->fields) ? 1 : 0;
	}
	if (error > 0)
	  DBUG_RETURN(-1);			/* purecov: inspected */
5288 5289 5290 5291 5292
	if (end_of_records)
	{
	  join->send_records++;
	  DBUG_RETURN(0);
	}
unknown's avatar
unknown committed
5293 5294
	if (!error &&
	    ++join->send_records >= join->thd->select_limit &&
5295 5296 5297 5298 5299 5300 5301
	    join->do_send_rows)
	{
	  if (!(join->select_options & OPTION_FOUND_ROWS))
	    DBUG_RETURN(-3);				// Abort nicely
	  join->do_send_rows=0;
	  join->thd->select_limit = HA_POS_ERROR;
        }
unknown's avatar
unknown committed
5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344
      }
    }
    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);
      init_sum_functions(join->sum_funcs);
      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
5345
    copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
5346

5347
#ifdef TO_BE_DELETED
unknown's avatar
unknown committed
5348 5349 5350 5351 5352 5353 5354 5355 5356 5357
    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)
	{
	  Field *field=item->tmp_table_field();
5358
	  field->ptr[-1]= (byte) (field->is_null() ? 1 : 0);
unknown's avatar
unknown committed
5359 5360 5361
	}
      }
    }
5362
#endif
unknown's avatar
unknown committed
5363 5364
    if (!join->having || join->having->val_int())
    {
unknown's avatar
unknown committed
5365
      join->found_records++;
unknown's avatar
unknown committed
5366 5367
      if ((error=table->file->write_row(table->record[0])))
      {
unknown's avatar
unknown committed
5368 5369 5370
	if (error == HA_ERR_FOUND_DUPP_KEY ||
	    error == HA_ERR_FOUND_DUPP_UNIQUE)
	  goto end;
unknown's avatar
unknown committed
5371 5372
	if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
				    error,1))
5373
	  DBUG_RETURN(-1);			// Not a table_is_full error
unknown's avatar
unknown committed
5374
	table->uniques=0;			// To ensure rows are the same
5375
      }
unknown's avatar
unknown committed
5376
      if (++join->send_records >= join->tmp_table_param.end_write_records &&
5377 5378 5379 5380 5381 5382 5383
	  join->do_send_rows)
      {
	if (!(join->select_options & OPTION_FOUND_ROWS))
	  DBUG_RETURN(-3);
	join->do_send_rows=0;
	join->thd->select_limit = HA_POS_ERROR;
	DBUG_RETURN(0);
unknown's avatar
unknown committed
5384 5385 5386
      }
    }
  }
unknown's avatar
unknown committed
5387
end:
unknown's avatar
unknown committed
5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410
  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
5411
  join->found_records++;
unknown's avatar
unknown committed
5412 5413 5414 5415 5416 5417
  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);
5418
    /* Store in the used key if the field was 0 */
unknown's avatar
unknown committed
5419
    if (item->maybe_null)
5420
      group->buff[-1]=item->null_value ? 1 : 0;
unknown's avatar
unknown committed
5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445
  }
  // table->file->index_init(0);
  if (!table->file->index_read(table->record[1],
			       join->tmp_table_param.group_buff,0,
			       HA_READ_KEY_EXACT))
  {						/* Update old record */
    restore_record(table,1);
    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
5446
  copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
5447 5448
  if ((error=table->file->write_row(table->record[0])))
  {
unknown's avatar
unknown committed
5449 5450
    if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
				error, 0))
unknown's avatar
unknown committed
5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479
      DBUG_RETURN(-1);				// Not a table_is_full error
    /* Change method to update rows */
    table->file->index_init(0);
    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
5480
  copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533

  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 */
    }
    restore_record(table,1);
    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)
5534 5535
	{
	  /* No matching rows for group function */
unknown's avatar
unknown committed
5536
	  clear_tables(join);
5537 5538
	  copy_fields(&join->tmp_table_param);
	}
unknown's avatar
unknown committed
5539 5540 5541 5542 5543
	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
5544 5545
	    if (create_myisam_from_heap(join->thd, table,
					&join->tmp_table_param, error, 0))
5546
	      DBUG_RETURN(-1);			// Not a table_is_full error
unknown's avatar
unknown committed
5547 5548 5549 5550 5551 5552 5553 5554 5555 5556
	  }
	  else
	    join->send_records++;
	}
	if (end_of_records)
	  DBUG_RETURN(0);
      }
    }
    else
    {
5557 5558
      if (end_of_records)
	DBUG_RETURN(0);
unknown's avatar
unknown committed
5559 5560 5561 5562 5563 5564
      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
5565
      copy_funcs(join->tmp_table_param.items_to_copy);
unknown's avatar
unknown committed
5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580
      init_sum_functions(join->sum_funcs);
      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);
}


/*****************************************************************************
5581 5582 5583 5584 5585
  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
5586 5587 5588 5589 5590 5591 5592
*****************************************************************************/

/* 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;
5593 5594
  // 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
5595 5596
  {
    Item *ref_item=part_of_refkey(field->table,field);
5597
    if (ref_item && ref_item->eq(right_item,1))
unknown's avatar
unknown committed
5598 5599
    {
      if (right_item->type() == Item::FIELD_ITEM)
unknown's avatar
unknown committed
5600
	return (field->eq_def(((Item_field *) right_item)->field));
5601
      if (right_item->const_item() && !(right_item->is_null()))
unknown's avatar
unknown committed
5602
      {
5603 5604 5605 5606
	/*
	  We can remove binary fields and numerical fields except float,
	  as float comparison isn't 100 % secure
	*/
unknown's avatar
unknown committed
5607 5608 5609
	if (field->binary() &&
	    (field->type() != FIELD_TYPE_FLOAT || field->decimals() == 0))
	{
unknown's avatar
unknown committed
5610
	  return !store_val_in_field(field,right_item);
unknown's avatar
unknown committed
5611 5612 5613 5614
	}
      }
    }
  }
unknown's avatar
unknown committed
5615
  return 0;					// keep test
unknown's avatar
unknown committed
5616 5617 5618 5619 5620 5621 5622
}


static COND *
make_cond_for_table(COND *cond,table_map tables,table_map used_table)
{
  if (used_table && !(cond->used_tables() & used_table))
unknown's avatar
unknown committed
5623
    return (COND*) 0;				// Already checked
unknown's avatar
unknown committed
5624 5625 5626 5627
  if (cond->type() == Item::COND_ITEM)
  {
    if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
    {
5628
      /* Create new top level AND item */
unknown's avatar
unknown committed
5629 5630
      Item_cond_and *new_cond=new Item_cond_and;
      if (!new_cond)
unknown's avatar
unknown committed
5631
	return (COND*) 0;			// OOM /* purecov: inspected */
unknown's avatar
unknown committed
5632 5633 5634 5635 5636 5637 5638 5639 5640 5641
      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:
unknown's avatar
unknown committed
5642
	return (COND*) 0;			// Always true
unknown's avatar
unknown committed
5643
      case 1:
unknown's avatar
unknown committed
5644
	return new_cond->argument_list()->head();
unknown's avatar
unknown committed
5645 5646 5647
      default:
	new_cond->used_tables_cache=((Item_cond*) cond)->used_tables_cache &
	  tables;
unknown's avatar
unknown committed
5648
	return new_cond;
unknown's avatar
unknown committed
5649 5650 5651 5652 5653 5654
      }
    }
    else
    {						// Or list
      Item_cond_or *new_cond=new Item_cond_or;
      if (!new_cond)
unknown's avatar
unknown committed
5655
	return (COND*) 0;			// OOM /* purecov: inspected */
unknown's avatar
unknown committed
5656 5657 5658 5659 5660 5661
      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)
unknown's avatar
unknown committed
5662
	  return (COND*) 0;			// Always true
unknown's avatar
unknown committed
5663 5664 5665
	new_cond->argument_list()->push_back(fix);
      }
      new_cond->used_tables_cache=((Item_cond_or*) cond)->used_tables_cache;
5666
      new_cond->top_level_item();
unknown's avatar
unknown committed
5667
      return new_cond;
unknown's avatar
unknown committed
5668 5669 5670 5671
    }
  }

  /*
5672 5673 5674
    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
5675 5676 5677
  */

  if (cond->marker == 3 || (cond->used_tables() & ~tables))
unknown's avatar
unknown committed
5678
    return (COND*) 0;				// Can't check this yet
unknown's avatar
unknown committed
5679
  if (cond->marker == 2 || cond->eq_cmp_result() == Item::COND_OK)
unknown's avatar
unknown committed
5680
    return cond;				// Not boolean op
unknown's avatar
unknown committed
5681 5682 5683 5684 5685 5686 5687 5688 5689

  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
unknown's avatar
unknown committed
5690
      return (COND*) 0;
unknown's avatar
unknown committed
5691 5692 5693 5694 5695
    }
    if (right_item->type() == Item::FIELD_ITEM &&
	test_if_ref((Item_field*) right_item,left_item))
    {
      cond->marker=3;			// Checked when read
unknown's avatar
unknown committed
5696
      return (COND*) 0;
unknown's avatar
unknown committed
5697 5698 5699
    }
  }
  cond->marker=2;
unknown's avatar
unknown committed
5700
  return cond;
unknown's avatar
unknown committed
5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714
}

static Item *
part_of_refkey(TABLE *table,Field *field)
{
  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) &&
	  !(key_part->key_part_flag & HA_PART_KEY))
unknown's avatar
unknown committed
5715
	return table->reginfo.join_tab->ref.items[part];
unknown's avatar
unknown committed
5716
  }
unknown's avatar
unknown committed
5717
  return (Item*) 0;
unknown's avatar
unknown committed
5718 5719 5720 5721
}


/*****************************************************************************
5722 5723 5724 5725 5726
  Test if one can use the key to resolve ORDER BY
  Returns: 1 if key is ok.
	   0 if key can't be used
	  -1 if reverse key can be used
          used_key_parts is set to key parts used if length != 0
unknown's avatar
unknown committed
5727 5728
*****************************************************************************/

unknown's avatar
unknown committed
5729 5730
static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
				uint *used_key_parts)
unknown's avatar
unknown committed
5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751
{
  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;

  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()
    */
    while (const_key_parts & 1)
    {
      key_part++; const_key_parts>>=1;
    }
    if (key_part == key_part_end || key_part->field != field)
unknown's avatar
unknown committed
5752
      return 0;
unknown's avatar
unknown committed
5753 5754 5755 5756 5757

    /* set flag to 1 if we can use read-next on key, else to -1 */
    flag=(order->asc == !(key_part->key_part_flag & HA_REVERSE_SORT))
      ? 1 : -1;
    if (reverse && flag != reverse)
unknown's avatar
unknown committed
5758
      return 0;
unknown's avatar
unknown committed
5759 5760 5761
    reverse=flag;				// Remember if reverse
    key_part++;
  }
unknown's avatar
unknown committed
5762
  *used_key_parts= (uint) (key_part - table->key_info[idx].key_part);
unknown's avatar
unknown committed
5763
  return reverse;
unknown's avatar
unknown committed
5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780
}

static uint find_shortest_key(TABLE *table, key_map usable_keys)
{
  uint min_length= (uint) ~0;
  uint best= MAX_KEY;
  for (uint nr=0; usable_keys ; usable_keys>>=1, nr++)
  {
    if (usable_keys & 1)
    {
      if (table->key_info[nr].key_length < min_length)
      {
	min_length=table->key_info[nr].key_length;
	best=nr;
      }
    }
  }
unknown's avatar
unknown committed
5781
  return best;
unknown's avatar
unknown committed
5782 5783 5784
}


5785 5786 5787 5788 5789 5790 5791 5792 5793 5794
/*
  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
5795 5796

static bool
5797 5798
test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
			bool no_changes)
unknown's avatar
unknown committed
5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814
{
  int ref_key;
  TABLE *table=tab->table;
  SQL_SELECT *select=tab->select;
  key_map usable_keys;
  DBUG_ENTER("test_if_skip_sort_order");

  /* Check which keys can be used to resolve ORDER BY */
  usable_keys= ~(key_map) 0;
  for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
  {
    if ((*tmp_order->item)->type() != Item::FIELD_ITEM)
    {
      usable_keys=0;
      break;
    }
5815
    usable_keys&=((Item_field*) (*tmp_order->item))->field->part_of_sortkey;
unknown's avatar
unknown committed
5816 5817 5818 5819 5820 5821 5822 5823 5824 5825
  }

  ref_key= -1;
  if (tab->ref.key >= 0)			// Constant range in WHERE
    ref_key=tab->ref.key;
  else if (select && select->quick)		// Range found by opt_range
    ref_key=select->quick->index;

  if (ref_key >= 0)
  {
5826 5827 5828
    /*
      We come here when there is a REF key.
    */
5829
    int order_direction;
unknown's avatar
unknown committed
5830
    uint used_key_parts;
unknown's avatar
unknown committed
5831 5832
    /* Check if we get the rows in requested sorted order by using the key */
    if ((usable_keys & ((key_map) 1 << ref_key)) &&
unknown's avatar
unknown committed
5833 5834
	(order_direction = test_if_order_by_key(order,table,ref_key,
						&used_key_parts)))
5835
    {
5836
      if (order_direction == -1)		// If ORDER BY ... DESC
5837
      {
unknown's avatar
unknown committed
5838 5839
	if (select && select->quick)
	{
5840 5841 5842 5843 5844
	  /*
	    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
5845
	  {
5846 5847
            if (table->file->index_flags(ref_key) & HA_NOT_READ_PREFIX_LAST)
              DBUG_RETURN(0);			// Use filesort
5848 5849 5850 5851 5852 5853 5854 5855 5856
	    // 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
5857 5858 5859 5860 5861 5862 5863
	  }
	  DBUG_RETURN(1);
	}
	if (tab->ref.key_parts < used_key_parts)
	{
	  /*
	    SELECT * FROM t1 WHERE a=1 ORDER BY a DESC,b DESC
5864 5865 5866

	    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
5867
	  */
5868
	  if (table->file->index_flags(ref_key) & HA_NOT_READ_PREFIX_LAST)
5869
	    DBUG_RETURN(0);			// Use filesort
5870 5871 5872
	  tab->read_first_record=       join_read_last_key;
	  tab->read_record.read_record= join_read_prev_same;
	  /* fall through */
unknown's avatar
unknown committed
5873
	}
5874
      }
unknown's avatar
unknown committed
5875
      DBUG_RETURN(1);			/* No need to sort */
5876
    }
unknown's avatar
unknown committed
5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890
  }
  else
  {
    /* check if we can use a key to resolve the group */
    /* Tables using JT_NEXT are handled here */
    uint nr;
    key_map keys=usable_keys;

    /*
      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
5891
      keys&= (table->used_keys | table->file->keys_to_use_for_scanning());
unknown's avatar
unknown committed
5892 5893 5894

    for (nr=0; keys ; keys>>=1, nr++)
    {
unknown's avatar
unknown committed
5895
      uint not_used;
unknown's avatar
unknown committed
5896 5897 5898
      if (keys & 1)
      {
	int flag;
unknown's avatar
unknown committed
5899
	if ((flag=test_if_order_by_key(order, table, nr, &not_used)))
unknown's avatar
unknown committed
5900
	{
5901 5902 5903
	  if (!no_changes)
	  {
	    tab->index=nr;
5904 5905
	    tab->read_first_record=  (flag > 0 ? join_read_first:
				      join_read_last);
5906 5907
	    table->file->index_init(nr);
	    tab->type=JT_NEXT;	// Read with index_first(), index_next()
unknown's avatar
unknown committed
5908 5909 5910 5911 5912
	    if (table->used_keys & ((key_map) 1 << nr))
	    {
	      table->key_read=1;
	      table->file->extra(HA_EXTRA_KEYREAD);
	    }
5913
	  }
unknown's avatar
unknown committed
5914 5915 5916 5917 5918 5919 5920 5921
	  DBUG_RETURN(1);
	}
      }
    }
  }
  DBUG_RETURN(0);				// Can't use index.
}

unknown's avatar
unknown committed
5922 5923 5924 5925 5926 5927 5928 5929

/*****************************************************************************
  If not selecting by given key, create an index how records should be read
  return: 0  ok
	  -1 some fatal error
	   1  no records
*****************************************************************************/

unknown's avatar
unknown committed
5930
static int
unknown's avatar
unknown committed
5931 5932
create_sort_index(JOIN_TAB *tab, ORDER *order, ha_rows filesort_limit,
		  ha_rows select_limit)
unknown's avatar
unknown committed
5933 5934 5935
{
  SORT_FIELD *sortorder;
  uint length;
5936
  ha_rows examined_rows;
unknown's avatar
unknown committed
5937 5938 5939 5940
  TABLE *table=tab->table;
  SQL_SELECT *select=tab->select;
  DBUG_ENTER("create_sort_index");

5941
  if (test_if_skip_sort_order(tab,order,select_limit,0))
unknown's avatar
unknown committed
5942 5943 5944 5945 5946
    DBUG_RETURN(0);
  if (!(sortorder=make_unireg_sortorder(order,&length)))
    goto err;				/* purecov: inspected */
  /* It's not fatal if the following alloc fails */
  table->io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
5947
					MYF(MY_WME | MY_ZEROFILL));
unknown's avatar
unknown committed
5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968
  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.
5969 5970
	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
5971
      */
unknown's avatar
unknown committed
5972
      if (!(select->quick=get_ft_or_quick_select_for_ref(table, tab)))
unknown's avatar
unknown committed
5973 5974 5975
	goto err;
    }
  }
5976 5977 5978
  if (table->tmp_table)
    table->file->info(HA_STATUS_VARIABLE);	// Get record count
  table->found_records=filesort(table,sortorder,length,
unknown's avatar
unknown committed
5979
				select, 0L, filesort_limit, &examined_rows);
5980
  tab->records=table->found_records;		// For SQL_CALC_ROWS
unknown's avatar
unknown committed
5981 5982 5983 5984 5985
  delete select;				// filesort did select
  tab->select=0;
  tab->select_cond=0;
  tab->type=JT_ALL;				// Read with normal read_record
  tab->read_first_record= join_init_read_record;
5986
  tab->join->examined_rows+=examined_rows;
unknown's avatar
unknown committed
5987 5988 5989 5990 5991 5992 5993 5994 5995 5996
  if (table->key_read)				// Restore if we used indexes
  {
    table->key_read=0;
    table->file->extra(HA_EXTRA_NO_KEYREAD);
  }
  DBUG_RETURN(table->found_records == HA_POS_ERROR);
err:
  DBUG_RETURN(-1);
}

5997
/*
5998
  Add the HAVING criteria to table->select
5999 6000
*/

unknown's avatar
unknown committed
6001
#ifdef NOT_YET
6002 6003 6004 6005 6006 6007
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
6008
  DBUG_EXECUTE("where",print_where(*having,"having"););
6009 6010 6011 6012 6013
  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))
unknown's avatar
unknown committed
6014
	return 1;
6015 6016 6017 6018 6019
    if (!table->select->cond)
      table->select->cond=sort_table_cond;
    else					// This should never happen
      if (!(table->select->cond=new Item_cond_and(table->select->cond,
						  sort_table_cond)))
unknown's avatar
unknown committed
6020
	return 1;
6021
    table->select_cond=table->select->cond;
6022
    table->select_cond->top_level_item();
6023 6024 6025 6026 6027
    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"););
  }
unknown's avatar
unknown committed
6028
  return 0;
6029
}
unknown's avatar
unknown committed
6030
#endif
6031 6032


unknown's avatar
unknown committed
6033
/*****************************************************************************
6034 6035 6036 6037 6038
  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
6039 6040 6041 6042 6043 6044 6045
*****************************************************************************/

static bool compare_record(TABLE *table, Field **ptr)
{
  for (; *ptr ; ptr++)
  {
    if ((*ptr)->cmp_offset(table->rec_buff_length))
unknown's avatar
unknown committed
6046
      return 1;
unknown's avatar
unknown committed
6047
  }
unknown's avatar
unknown committed
6048
  return 0;
unknown's avatar
unknown committed
6049 6050 6051 6052 6053 6054 6055 6056
}

static bool copy_blobs(Field **ptr)
{
  for (; *ptr ; ptr++)
  {
    if ((*ptr)->flags & BLOB_FLAG)
      if (((Field_blob *) (*ptr))->copy())
unknown's avatar
unknown committed
6057
	return 1;				// Error
unknown's avatar
unknown committed
6058
  }
unknown's avatar
unknown committed
6059
  return 0;
unknown's avatar
unknown committed
6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072
}

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


static int
6073
remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
unknown's avatar
unknown committed
6074 6075 6076 6077
{
  int error;
  ulong reclength,offset;
  uint field_count;
unknown's avatar
unknown committed
6078
  THD *thd= join->thd;
unknown's avatar
unknown committed
6079 6080 6081 6082 6083 6084 6085 6086 6087
  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
6088 6089
  {
    if (item->tmp_table_field() && ! item->const_item())
unknown's avatar
unknown committed
6090
      field_count++;
unknown's avatar
unknown committed
6091
  }
unknown's avatar
unknown committed
6092 6093 6094

  if (!field_count)
  {						// only const items
unknown's avatar
unknown committed
6095
    join->thd->select_limit=1;	// Only send first row
unknown's avatar
unknown committed
6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106
    DBUG_RETURN(0);
  }
  Field **first_field=entry->field+entry->fields - field_count;
  offset=entry->field[entry->fields - field_count]->offset();
  reclength=entry->reclength-offset;

  free_io_cache(entry);				// Safety
  entry->file->info(HA_STATUS_VARIABLE);
  if (entry->db_type == DB_TYPE_HEAP ||
      (!entry->blob_fields &&
       ((ALIGN_SIZE(reclength) +sizeof(HASH_LINK)) * entry->file->records <
6107
	thd->variables.sortbuff_size)))
unknown's avatar
unknown committed
6108 6109
    error=remove_dup_with_hash_index(join->thd, entry,
				     field_count, first_field,
6110
				     reclength, having);
unknown's avatar
unknown committed
6111
  else
6112 6113
    error=remove_dup_with_compare(join->thd, entry, first_field, offset,
				  having);
unknown's avatar
unknown committed
6114 6115 6116 6117 6118 6119 6120

  free_blobs(first_field);
  DBUG_RETURN(error);
}


static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
6121
				   ulong offset, Item *having)
unknown's avatar
unknown committed
6122 6123 6124
{
  handler *file=table->file;
  char *org_record,*new_record;
unknown's avatar
unknown committed
6125
  byte *record;
unknown's avatar
unknown committed
6126 6127 6128 6129
  int error;
  ulong reclength=table->reclength-offset;
  DBUG_ENTER("remove_dup_with_compare");

6130
  org_record=(char*) (record=table->record[0])+offset;
unknown's avatar
unknown committed
6131 6132 6133
  new_record=(char*) table->record[1]+offset;

  file->rnd_init();
6134
  error=file->rnd_next(record);
unknown's avatar
unknown committed
6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150
  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;
    }
6151 6152 6153 6154
    if (having && !having->val_int())
    {
      if ((error=file->delete_row(record)))
	goto err;
6155
      error=file->rnd_next(record);
6156 6157
      continue;
    }
unknown's avatar
unknown committed
6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169
    if (copy_blobs(first_field))
    {
      my_error(ER_OUT_OF_SORTMEMORY,MYF(0));
      error=0;
      goto err;
    }
    memcpy(new_record,org_record,reclength);

    /* Read through rest of file and mark duplicated rows deleted */
    bool found=0;
    for (;;)
    {
6170
      if ((error=file->rnd_next(record)))
unknown's avatar
unknown committed
6171 6172 6173 6174 6175 6176 6177 6178 6179
      {
	if (error == HA_ERR_RECORD_DELETED)
	  continue;
	if (error == HA_ERR_END_OF_FILE)
	  break;
	goto err;
      }
      if (compare_record(table, first_field) == 0)
      {
6180
	if ((error=file->delete_row(record)))
unknown's avatar
unknown committed
6181 6182 6183 6184 6185
	  goto err;
      }
      else if (!found)
      {
	found=1;
6186
	file->position(record);	// Remember position
unknown's avatar
unknown committed
6187 6188 6189 6190 6191
      }
    }
    if (!found)
      break;					// End of file
    /* Restart search on next row */
6192
    error=file->restart_rnd_next(record,file->ref);
unknown's avatar
unknown committed
6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212
  }

  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,
6213 6214
				      ulong key_length,
				      Item *having)
unknown's avatar
unknown committed
6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261
{
  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);
  if (hash_init(&hash, (uint) file->records, 0, key_length,
		(hash_get_key) 0, 0, 0))
  {
    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();
  }

  file->rnd_init();
  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;
    }
6262 6263 6264 6265 6266
    if (having && !having->val_int())
    {
      if ((error=file->delete_row(record)))
	goto err;
      continue;
6267
    }
unknown's avatar
unknown committed
6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282

    /* 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;
    }
6283 6284
    else
      (void) hash_insert(&hash, key_pos-key_length);
unknown's avatar
unknown committed
6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303
    key_pos+=extra_length;
  }
  my_free((char*) key_buffer,MYF(0));
  hash_free(&hash);
  file->extra(HA_EXTRA_NO_CACHE);
  (void) file->rnd_end();
  DBUG_RETURN(0);

err:
  my_free((char*) key_buffer,MYF(0));
  hash_free(&hash);
  file->extra(HA_EXTRA_NO_CACHE);
  (void) file->rnd_end();
  if (error)
    file->print_error(error,MYF(0));
  DBUG_RETURN(1);
}


unknown's avatar
unknown committed
6304
SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
unknown's avatar
unknown committed
6305 6306 6307 6308 6309 6310 6311 6312 6313 6314
{
  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)
unknown's avatar
unknown committed
6315
    return 0;
unknown's avatar
unknown committed
6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338

  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())
      pos->field= ((Item_sum*) order->item[0])->tmp_table_field();
    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);
}


/*****************************************************************************
6339 6340 6341 6342
  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
6343 6344 6345 6346 6347 6348 6349 6350 6351
******************************************************************************/

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;
6352
  JOIN_TAB *join_tab;
unknown's avatar
unknown committed
6353 6354 6355 6356 6357
  DBUG_ENTER("join_init_cache");

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

6358 6359
  join_tab=tables;
  for (i=0 ; i < table_count ; i++,join_tab++)
unknown's avatar
unknown committed
6360
  {
6361 6362 6363 6364
    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
6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403
  }
  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;
6404
      copy->length=tables[i].table->null_bytes;
unknown's avatar
unknown committed
6405 6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427
      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->records=0; cache->ptr_record= (uint) ~0;
  cache->length=length+blobs*sizeof(char*);
  cache->blobs=blobs;
  *blob_ptr=0;					/* End sequentel */
6428
  size=max(thd->variables.join_buff_size, cache->length);
unknown's avatar
unknown committed
6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446
  if (!(cache->buff=(uchar*) my_malloc(size,MYF(0))))
    DBUG_RETURN(1);				/* Don't use cache */ /* purecov: inspected */
  cache->end=cache->buff+size;
  reset_cache(cache);
  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);
  }
unknown's avatar
unknown committed
6447
  return length;
unknown's avatar
unknown committed
6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468
}


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;

  /*
6469
    There is room in cache. Put record there
unknown's avatar
unknown committed
6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508
  */
  cache->records++;
  for (copy=cache->field ; copy < end_field; copy++)
  {
    if (copy->blob_field)
    {
      if (last_record)
      {
	copy->blob_field->get_image((char*) pos,copy->length+sizeof(char*));
	pos+=copy->length+sizeof(char*);
      }
      else
      {
	copy->blob_field->get_image((char*) pos,copy->length); // blob length
	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;
unknown's avatar
unknown committed
6509
  return last_record || (uint) (cache->end -pos) < cache->length;
unknown's avatar
unknown committed
6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564
}


static void
reset_cache(JOIN_CACHE *cache)
{
  cache->record_nr=0;
  cache->pos=cache->buff;
}


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)
      {
	copy->blob_field->set_image((char*) pos,copy->length+sizeof(char*));
	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;
unknown's avatar
unknown committed
6565
  return;
unknown's avatar
unknown committed
6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577
}


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)
unknown's avatar
unknown committed
6578 6579 6580
    return 1;
  return memcmp(tab->ref.key_buff2, tab->ref.key_buff, tab->ref.key_length)
    != 0;
unknown's avatar
unknown committed
6581 6582 6583 6584 6585 6586 6587 6588
}


bool
cp_buffer_from_ref(TABLE_REF *ref)
{
  for (store_key **copy=ref->key_copy ; *copy ; copy++)
    if ((*copy)->copy())
unknown's avatar
unknown committed
6589 6590
      return 1;					// Something went wrong
  return 0;
unknown's avatar
unknown committed
6591 6592 6593 6594
}


/*****************************************************************************
6595
  Group and order functions
unknown's avatar
unknown committed
6596 6597 6598
*****************************************************************************/

/*
6599 6600 6601
  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
6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619
*/

static int
find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
		   List<Item> &all_fields)
{
  if ((*order->item)->type() == Item::INT_ITEM)
  {						/* Order by position */
    Item *item=0;
    List_iterator<Item> li(fields);

    for (uint count= (uint) ((Item_int*) (*order->item))->value ;
	 count-- && (item=li++) ;) ;
    if (!item)
    {
      my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),
		      MYF(0),(*order->item)->full_name(),
	       thd->where);
unknown's avatar
unknown committed
6620
      return 1;
unknown's avatar
unknown committed
6621 6622 6623
    }
    order->item=li.ref();
    order->in_field_list=1;
unknown's avatar
unknown committed
6624
    return 0;
unknown's avatar
unknown committed
6625 6626 6627 6628 6629 6630 6631 6632 6633
  }
  const char *save_where=thd->where;
  thd->where=0;					// No error if not found
  Item **item=find_item_in_list(*order->item,fields);
  thd->where=save_where;
  if (item)
  {
    order->item=item;				// use it
    order->in_field_list=1;
unknown's avatar
unknown committed
6634
    return 0;
unknown's avatar
unknown committed
6635 6636 6637
  }
  order->in_field_list=0;
  if ((*order->item)->fix_fields(thd,tables) || thd->fatal_error)
unknown's avatar
unknown committed
6638
    return 1;					// Wrong field
unknown's avatar
unknown committed
6639 6640
  all_fields.push_front(*order->item);		// Add new field to field list
  order->item=(Item**) all_fields.head_ref();
unknown's avatar
unknown committed
6641
  return 0;
unknown's avatar
unknown committed
6642 6643 6644 6645
}


/*
6646 6647
  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
6648 6649
*/

unknown's avatar
unknown committed
6650
int setup_order(THD *thd,TABLE_LIST *tables,List<Item> &fields,
unknown's avatar
unknown committed
6651 6652 6653 6654 6655 6656
	     List<Item> &all_fields, ORDER *order)
{
  thd->where="order clause";
  for (; order; order=order->next)
  {
    if (find_order_in_list(thd,tables,order,fields,all_fields))
unknown's avatar
unknown committed
6657
      return 1;
unknown's avatar
unknown committed
6658
  }
unknown's avatar
unknown committed
6659
  return 0;
unknown's avatar
unknown committed
6660 6661 6662 6663 6664 6665 6666 6667 6668
}


static int
setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
	    List<Item> &all_fields, ORDER *order, bool *hidden_group_fields)
{
  *hidden_group_fields=0;
  if (!order)
unknown's avatar
unknown committed
6669
    return 0;				/* Everything is ok */
unknown's avatar
unknown committed
6670

6671
  if (thd->sql_mode & MODE_ONLY_FULL_GROUP_BY)
unknown's avatar
unknown committed
6672 6673 6674 6675 6676 6677 6678 6679 6680
  {
    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";
6681
  for (; order; order=order->next)
unknown's avatar
unknown committed
6682 6683
  {
    if (find_order_in_list(thd,tables,order,fields,all_fields))
unknown's avatar
unknown committed
6684
      return 1;
unknown's avatar
unknown committed
6685 6686 6687 6688 6689
    (*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());
unknown's avatar
unknown committed
6690
      return 1;
unknown's avatar
unknown committed
6691 6692
    }
  }
6693
  if (thd->sql_mode & MODE_ONLY_FULL_GROUP_BY)
unknown's avatar
unknown committed
6694 6695 6696 6697 6698 6699 6700
  {
    /* Don't allow one to use fields that is not used in GROUP BY */
    Item *item;
    List_iterator<Item> li(fields);

    while ((item=li++))
    {
6701 6702
      if (item->type() != Item::SUM_FUNC_ITEM && !item->marker &&
	  !item->const_item())
unknown's avatar
unknown committed
6703 6704 6705 6706
      {
	my_printf_error(ER_WRONG_FIELD_WITH_GROUP,
			ER(ER_WRONG_FIELD_WITH_GROUP),
			MYF(0),item->full_name());
unknown's avatar
unknown committed
6707
	return 1;
unknown's avatar
unknown committed
6708 6709 6710 6711 6712
      }
    }
  }
  if (org_fields != all_fields.elements)
    *hidden_group_fields=1;			// group fields is not used
unknown's avatar
unknown committed
6713
  return 0;
unknown's avatar
unknown committed
6714 6715 6716
}

/*
6717
  Add fields with aren't used at start of field list. Return FALSE if ok
unknown's avatar
unknown committed
6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728
*/

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...
  thd->where=0;					// Don't give error
6729
  for (; new_field ; new_field=new_field->next)
unknown's avatar
unknown committed
6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746
  {
    if ((item=find_item_in_list(*new_field->item,fields)))
      new_field->item=item;			/* Change to shared Item */
    else
    {
      thd->where="procedure list";
      if ((*new_field->item)->fix_fields(thd,tables))
	DBUG_RETURN(1); /* purecov: inspected */
      thd->where=0;
      all_fields.push_front(*new_field->item);
      new_field->item=all_fields.head_ref();
    }
  }
  DBUG_RETURN(0);
}

/*
6747 6748 6749
  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
6750 6751 6752
*/

static ORDER *
6753 6754
create_distinct_group(THD *thd, ORDER *order_list, List<Item> &fields, 
		      bool *all_order_by_fields_used)
unknown's avatar
unknown committed
6755 6756 6757 6758 6759
{
  List_iterator<Item> li(fields);
  Item *item;
  ORDER *order,*group,**prev;

6760
  *all_order_by_fields_used= 1;
unknown's avatar
unknown committed
6761 6762 6763 6764 6765 6766 6767 6768
  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)
    {
6769
      ORDER *ord=(ORDER*) thd->memdup((char*) order,sizeof(ORDER));
unknown's avatar
unknown committed
6770
      if (!ord)
unknown's avatar
unknown committed
6771
	return 0;
unknown's avatar
unknown committed
6772 6773 6774 6775
      *prev=ord;
      prev= &ord->next;
      (*ord->item)->marker=1;
    }
6776 6777
    else
      *all_order_by_fields_used= 0;
unknown's avatar
unknown committed
6778 6779 6780 6781 6782 6783 6784 6785 6786
  }

  li.rewind();
  while ((item=li++))
  {
    if (item->const_item() || item->with_sum_func)
      continue;
    if (!item->marker)
    {
6787
      ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER));
unknown's avatar
unknown committed
6788
      if (!ord)
unknown's avatar
unknown committed
6789
	return 0;
unknown's avatar
unknown committed
6790 6791 6792 6793 6794 6795 6796
      ord->item=li.ref();
      ord->asc=1;
      *prev=ord;
      prev= &ord->next;
    }
  }
  *prev=0;
unknown's avatar
unknown committed
6797
  return group;
unknown's avatar
unknown committed
6798 6799 6800 6801
}


/*****************************************************************************
6802
  Update join with count of the different type of fields
unknown's avatar
unknown committed
6803 6804 6805
*****************************************************************************/

void
unknown's avatar
unknown committed
6806 6807
count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
		  bool reset_with_sum_func)
unknown's avatar
unknown committed
6808 6809 6810 6811
{
  List_iterator<Item> li(fields);
  Item *field;

6812
  param->field_count=param->sum_func_count=param->func_count=
unknown's avatar
unknown committed
6813
    param->hidden_field_count=0;
unknown's avatar
unknown committed
6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838
  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
6839
    {
unknown's avatar
unknown committed
6840
      param->func_count++;
unknown's avatar
unknown committed
6841 6842 6843
      if (reset_with_sum_func)
	field->with_sum_func=0;
    }
unknown's avatar
unknown committed
6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858
  }
}


/*
  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)
  {
6859
    if ((*a->item)->eq(*b->item,1))
unknown's avatar
unknown committed
6860 6861
      a->asc=b->asc;
    else
unknown's avatar
unknown committed
6862
      return 0;
unknown's avatar
unknown committed
6863
  }
unknown's avatar
unknown committed
6864
  return test(!b);
unknown's avatar
unknown committed
6865 6866 6867 6868 6869 6870 6871 6872 6873 6874 6875 6876 6877 6878 6879 6880 6881 6882 6883 6884 6885
}

/*
  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)
  {
6886
    if (!(*a->item)->eq(*b->item,1))
unknown's avatar
unknown committed
6887 6888 6889 6890 6891 6892
      DBUG_RETURN(0);
    map|=a->item[0]->used_tables();
  }
  if (!map || (map & RAND_TABLE_BIT))
    DBUG_RETURN(0);

6893
  for (; !(map & tables->table->map) ; tables=tables->next) ;
unknown's avatar
unknown committed
6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905
  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)
{
6906 6907
  uint key_length=0, parts=0, null_parts=0;

unknown's avatar
unknown committed
6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927
  if (group)
    join->group= 1;
  for (; group ; group=group->next)
  {
    Field *field=(*group->item)->tmp_table_field();
    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)
6928
      null_parts++;
unknown's avatar
unknown committed
6929
  }
6930
  join->tmp_table_param.group_length=key_length+null_parts;
unknown's avatar
unknown committed
6931
  join->tmp_table_param.group_parts=parts;
6932
  join->tmp_table_param.group_null_parts=null_parts;
unknown's avatar
unknown committed
6933 6934 6935 6936
}


/*
6937 6938
  Get a list of buffers for saveing last group
  Groups are saved in reverse order for easyer check loop
unknown's avatar
unknown committed
6939 6940 6941 6942 6943 6944 6945 6946 6947 6948 6949
*/

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))
unknown's avatar
unknown committed
6950
	return TRUE;
unknown's avatar
unknown committed
6951 6952 6953
    }
  }
  join->sort_and_group=1;			/* Mark for do_select */
unknown's avatar
unknown committed
6954
  return FALSE;
unknown's avatar
unknown committed
6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969
}


static int
test_if_group_changed(List<Item_buff> &list)
{
  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;
  }
unknown's avatar
unknown committed
6970
  return idx;
unknown's avatar
unknown committed
6971 6972 6973 6974 6975
}



/*
6976 6977 6978 6979
  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
unknown's avatar
unknown committed
6980 6981 6982
*/

bool
unknown's avatar
unknown committed
6983
setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields)
unknown's avatar
unknown committed
6984 6985 6986 6987 6988 6989 6990
{
  Item *pos;
  List_iterator<Item> li(fields);
  Copy_field *copy;
  DBUG_ENTER("setup_copy_fields");

  if (!(copy=param->copy_field= new Copy_field[param->field_count]))
6991
    goto err2;
unknown's avatar
unknown committed
6992 6993 6994 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010

  param->copy_funcs.empty();
  while ((pos=li++))
  {
    if (pos->type() == Item::FIELD_ITEM)
    {
      Item_field *item=(Item_field*) pos;
      if (item->field->flags & BLOB_FLAG)
      {
	if (!(pos=new Item_copy_string(pos)))
	  goto err;
	VOID(li.replace(pos));
	if (param->copy_funcs.push_back(pos))
	  goto err;
	continue;
      }

      /* set up save buffer and change result_field to point at saved value */
      Field *field= item->field;
unknown's avatar
unknown committed
7011
      item->result_field=field->new_field(&thd->mem_root,field->table);
unknown's avatar
unknown committed
7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035
      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++;
    }
    else if ((pos->type() == Item::FUNC_ITEM ||
	      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;
      VOID(li.replace(pos));
      if (param->copy_funcs.push_back(pos))
	goto err;
    }
  }
unknown's avatar
unknown committed
7036
  param->copy_field_end= copy;
unknown's avatar
unknown committed
7037 7038 7039
  DBUG_RETURN(0);

 err:
7040
  delete [] param->copy_field;			// This is never 0
unknown's avatar
unknown committed
7041
  param->copy_field=0;
7042
err2:
unknown's avatar
unknown committed
7043 7044 7045 7046 7047
  DBUG_RETURN(TRUE);
}


/*
7048
  Copy fields and null values between two tables
unknown's avatar
unknown committed
7049 7050 7051 7052 7053 7054
*/

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

7057
  for (; ptr != end; ptr++)
unknown's avatar
unknown committed
7058 7059
    (*ptr->do_copy)(ptr);

unknown's avatar
unknown committed
7060 7061
  List_iterator_fast<Item> &it=param->copy_funcs_it;
  it.rewind();
unknown's avatar
unknown committed
7062 7063 7064 7065 7066 7067 7068
  Item_copy_string *item;
  while ((item = (Item_copy_string*) it++))
    item->copy();
}


/*****************************************************************************
7069
  Make an array of pointer to sum_functions to speed up sum_func calculation
unknown's avatar
unknown committed
7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100
*****************************************************************************/

static bool
make_sum_func_list(JOIN *join,List<Item> &fields)
{
  DBUG_ENTER("make_sum_func_list");
  Item_sum **func =
    (Item_sum**) sql_alloc(sizeof(Item_sum*)*
			   (join->tmp_table_param.sum_func_count+1));
  if (!func)
    DBUG_RETURN(TRUE);
  List_iterator<Item> it(fields);
  join->sum_funcs=func;

  Item *field;
  while ((field=it++))
  {
    if (field->type() == Item::SUM_FUNC_ITEM && !field->const_item())
    {
      *func++=(Item_sum*) field;
      /* let COUNT(DISTINCT) create the temporary table */
      if (((Item_sum*) field)->setup(join->thd))
	DBUG_RETURN(TRUE);
    }
  }
  *func=0;					// End marker
  DBUG_RETURN(FALSE);
}


/*
7101
  Change all funcs and sum_funcs to fields in tmp table
unknown's avatar
unknown committed
7102 7103 7104
*/

static bool
7105
change_to_use_tmp_fields(List<Item> &items)
unknown's avatar
unknown committed
7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126
{
  List_iterator<Item> it(items);
  Item *item_field,*item;

  while ((item=it++))
  {
    Field *field;
    if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
      continue;
    if (item->type() == Item::FIELD_ITEM)
    {
      ((Item_field*) item)->field=
	((Item_field*) item)->result_field;
    }
    else if ((field=item->tmp_table_field()))
    {
      if (item->type() == Item::SUM_FUNC_ITEM && field->table->group)
	item_field=((Item_sum*) item)->result_item(field);
      else
	item_field=(Item*) new Item_field(field);
      if (!item_field)
unknown's avatar
unknown committed
7127
	return TRUE;				// Fatal error
unknown's avatar
unknown committed
7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145
      item_field->name=item->name;		/*lint -e613 */
#ifndef DBUG_OFF
      if (_db_on_ && !item_field->name)
      {
	char buff[256];
	String str(buff,sizeof(buff));
	str.length(0);
	item->print(&str);
	item_field->name=sql_strmake(str.ptr(),str.length());
      }
#endif
#ifdef DELETE_ITEMS
      delete it.replace(item_field);		/*lint -e613 */
#else
      (void) it.replace(item_field);		/*lint -e613 */
#endif
    }
  }
unknown's avatar
unknown committed
7146
  return FALSE;
unknown's avatar
unknown committed
7147 7148 7149 7150
}


/*
7151 7152
  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
7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201
*/

static bool
change_refs_to_tmp_fields(THD *thd,List<Item> &items)
{
  List_iterator<Item> it(items);
  Item *item;

  while ((item= it++))
  {
    if (item->type() == Item::SUM_FUNC_ITEM)
    {
      if (!item->const_item())
      {
	Item_sum *sum_item= (Item_sum*) item;
	if (sum_item->result_field)		// If not a const sum func
	{
	  Field *result_field=sum_item->result_field;
	  for (uint i=0 ; i < sum_item->arg_count ; i++)
	  {
	    Item *arg= sum_item->args[i];
	    if (!arg->const_item())
	    {
	      if (arg->type() == Item::FIELD_ITEM)
		((Item_field*) arg)->field= result_field++;
	      else
		sum_item->args[i]= new Item_field(result_field++);
	    }
	  }
	}
      }
    }
    else if (item->with_sum_func)
      continue;
    else if ((item->type() == Item::FUNC_ITEM ||
	      item->type() == Item::COND_ITEM) &&
	     !item->const_item())
    {						/* All funcs are stored */
#ifdef DELETE_ITEMS
      delete it.replace(new Item_field(((Item_func*) item)->result_field));
#else
      (void) it.replace(new Item_field(((Item_func*) item)->result_field));
#endif
    }
    else if (item->type() == Item::FIELD_ITEM)	/* Change refs */
    {
      ((Item_field*)item)->field=((Item_field*) item)->result_field;
    }
  }
unknown's avatar
unknown committed
7202
  return thd->fatal_error;
unknown's avatar
unknown committed
7203 7204 7205 7206 7207
}



/******************************************************************************
7208
  Code for calculating functions
unknown's avatar
unknown committed
7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238
******************************************************************************/

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++)))
    func->update_field(0);
}


	/* 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
7239
    (void) func->save_in_result_field(1);
unknown's avatar
unknown committed
7240
  return;
unknown's avatar
unknown committed
7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258
}


static void
init_sum_functions(Item_sum **func_ptr)
{
  Item_sum *func;
  for (; (func= (Item_sum*) *func_ptr) ; func_ptr++)
    func->reset();
}


static bool
update_sum_func(Item_sum **func_ptr)
{
  Item_sum *func;
  for (; (func= (Item_sum*) *func_ptr) ; func_ptr++)
    if (func->add())
unknown's avatar
unknown committed
7259 7260
      return 1;
  return 0;
unknown's avatar
unknown committed
7261 7262 7263 7264 7265
}

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

void
unknown's avatar
unknown committed
7266
copy_funcs(Item **func_ptr)
unknown's avatar
unknown committed
7267
{
unknown's avatar
unknown committed
7268
  Item *func;
unknown's avatar
unknown committed
7269
  for (; (func = *func_ptr) ; func_ptr++)
unknown's avatar
unknown committed
7270
    func->save_in_result_field(1);
unknown's avatar
unknown committed
7271 7272 7273 7274
}


/*****************************************************************************
7275 7276
  Create a condition for a const reference and add this to the
  currenct select for the table
unknown's avatar
unknown committed
7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298
*****************************************************************************/

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++)
  {
    Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i].fieldnr-1];
    Item *value=join_tab->ref.items[i];
    cond->add(new Item_func_equal(new Item_field(field),value));
  }
  if (thd->fatal_error)
    DBUG_RETURN(TRUE);
7299 7300 7301 7302 7303

  /*
    Here we pass 0 as the first argument to fix_fields that don't need
    to do any stack checking (This is already done in the initial fix_fields).
  */
unknown's avatar
unknown committed
7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316
  cond->fix_fields((THD *) 0,(TABLE_LIST *) 0);
  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);
}

/****************************************************************************
7317
  Send a description about what how the select will be done to stdout
unknown's avatar
unknown committed
7318 7319
****************************************************************************/

unknown's avatar
unknown committed
7320
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
unknown's avatar
unknown committed
7321
			    bool distinct,const char *message)
unknown's avatar
unknown committed
7322 7323 7324
{
  List<Item> field_list;
  Item *item;
7325
  List<Item> item_list;
unknown's avatar
unknown committed
7326
  THD *thd=join->thd;
7327
  MYSQL_LOCK *save_lock;
unknown's avatar
unknown committed
7328
  SELECT_LEX *select_lex = &(join->thd->lex.select_lex);
7329
  select_result *result=join->result;
7330
  Item *item_null= new Item_null();
unknown's avatar
unknown committed
7331
  DBUG_ENTER("select_describe");
unknown's avatar
unknown committed
7332

7333
  /* Don't log this into the slow query log */
unknown's avatar
unknown committed
7334
  select_lex->options&= ~(QUERY_NO_INDEX_USED | QUERY_NO_GOOD_INDEX_USED);
7335
  thd->offset_limit=0;
7336
  if (thd->lex.select == select_lex)
unknown's avatar
unknown committed
7337 7338 7339 7340
  {
    field_list.push_back(new Item_empty_string("table",NAME_LEN));
    field_list.push_back(new Item_empty_string("type",10));
    field_list.push_back(item=new Item_empty_string("possible_keys",
unknown's avatar
unknown committed
7341
						  NAME_LEN*MAX_KEY));
unknown's avatar
unknown committed
7342 7343 7344 7345 7346 7347 7348 7349 7350 7351
    item->maybe_null=1;
    field_list.push_back(item=new Item_empty_string("key",NAME_LEN));
    item->maybe_null=1;
    field_list.push_back(item=new Item_int("key_len",0,3));
    item->maybe_null=1;
    field_list.push_back(item=new Item_empty_string("ref",
						    NAME_LEN*MAX_REF_PARTS));
    item->maybe_null=1;
    field_list.push_back(new Item_real("rows",0.0,0,10));
    field_list.push_back(new Item_empty_string("Extra",255));
7352
    if (result->send_fields(field_list,1))
unknown's avatar
unknown committed
7353
      return;
unknown's avatar
unknown committed
7354
  }
7355

unknown's avatar
unknown committed
7356
  if (message)
unknown's avatar
unknown committed
7357
  {
7358 7359 7360
    Item *empty= new Item_empty_string("",0);
    for (uint i=0 ; i < 7; i++)
      item_list.push_back(empty);
7361 7362 7363
    item_list.push_back(new Item_string(message,strlen(message)));
    if (result->send_data(item_list))
      result->send_error(0,NullS);
unknown's avatar
unknown committed
7364 7365 7366 7367 7368
  }
  else
  {
    table_map used_tables=0;
    for (uint i=0 ; i < join->tables ; i++)
unknown's avatar
unknown committed
7369
    {
unknown's avatar
unknown committed
7370 7371
      JOIN_TAB *tab=join->join_tab+i;
      TABLE *table=tab->table;
7372
      char buff[512],*buff_ptr=buff;
7373
      char buff1[512], buff2[512], buff3[512];
7374 7375
      String tmp1(buff1,sizeof(buff1));
      String tmp2(buff2,sizeof(buff2));
7376 7377
      tmp1.length(0);
      tmp2.length(0);
7378
      item_list.empty();
7379

unknown's avatar
unknown committed
7380 7381
      if (tab->type == JT_ALL && tab->select && tab->select->quick)
	tab->type= JT_RANGE;
7382 7383 7384 7385
      item_list.push_back(new Item_string(table->table_name,
					  strlen(table->table_name)));
      item_list.push_back(new Item_string(join_type_str[tab->type],
					  strlen(join_type_str[tab->type])));
unknown's avatar
unknown committed
7386 7387 7388
      key_map bits;
      uint j;
      for (j=0,bits=tab->keys ; bits ; j++,bits>>=1)
unknown's avatar
unknown committed
7389
      {
unknown's avatar
unknown committed
7390 7391
	if (bits & 1)
	{
7392 7393 7394
	  if (tmp1.length())
	    tmp1.append(',');
	  tmp1.append(table->key_info[j].name);
unknown's avatar
unknown committed
7395
	}
unknown's avatar
unknown committed
7396
      }
7397 7398
      if (tmp1.length())
	item_list.push_back(new Item_string(tmp1.ptr(),tmp1.length()));
unknown's avatar
unknown committed
7399
      else
7400
	item_list.push_back(item_null);
unknown's avatar
unknown committed
7401
      if (tab->ref.key_parts)
unknown's avatar
unknown committed
7402
      {
7403 7404 7405
	KEY *key_info=table->key_info+ tab->ref.key;
	item_list.push_back(new Item_string(key_info->name,
					    strlen(key_info->name)));
7406
	item_list.push_back(new Item_int((int32) tab->ref.key_length));
unknown's avatar
unknown committed
7407 7408
	for (store_key **ref=tab->ref.key_copy ; *ref ; ref++)
	{
7409 7410 7411
	  if (tmp2.length())
	    tmp2.append(',');
	  tmp2.append((*ref)->name());
unknown's avatar
unknown committed
7412
	}
7413
	item_list.push_back(new Item_string(tmp2.ptr(),tmp2.length()));
unknown's avatar
unknown committed
7414 7415 7416
      }
      else if (tab->type == JT_NEXT)
      {
7417 7418 7419 7420 7421
	KEY *key_info=table->key_info+ tab->index;
	item_list.push_back(new Item_string(key_info->name,
					    strlen(key_info->name)));
	item_list.push_back(new Item_int((int32) key_info->key_length));
	item_list.push_back(item_null);
unknown's avatar
unknown committed
7422 7423 7424
      }
      else if (tab->select && tab->select->quick)
      {
7425 7426 7427
	KEY *key_info=table->key_info+ tab->select->quick->index;
	item_list.push_back(new Item_string(key_info->name,
					    strlen(key_info->name)));
7428
	item_list.push_back(new Item_int((int32) tab->select->quick->max_used_key_length));
7429
	item_list.push_back(item_null);
unknown's avatar
unknown committed
7430 7431 7432
      }
      else
      {
7433 7434 7435
	item_list.push_back(item_null);
	item_list.push_back(item_null);
	item_list.push_back(item_null);
unknown's avatar
unknown committed
7436
      }
7437 7438
      sprintf(buff3,"%.0f",join->best_positions[i].records_read);
      item_list.push_back(new Item_string(buff3,strlen(buff3)));
unknown's avatar
unknown committed
7439 7440 7441 7442 7443 7444
      my_bool key_read=table->key_read;
      if (tab->type == JT_NEXT &&
	  ((table->used_keys & ((key_map) 1 << tab->index))))
	key_read=1;
      
      if (tab->info)
7445
	item_list.push_back(new Item_string(tab->info,strlen(tab->info)));
7446
      else
unknown's avatar
unknown committed
7447
      {
7448
	if (tab->select)
unknown's avatar
unknown committed
7449
	{
7450 7451 7452 7453 7454 7455 7456 7457
	  if (tab->use_quick == 2)
	  {
	    sprintf(buff_ptr,"; Range checked for each record (index map: %u)",
		    tab->keys);
	    buff_ptr=strend(buff_ptr);
	  }
	  else
	    buff_ptr=strmov(buff_ptr,"; Using where");
unknown's avatar
unknown committed
7458
	}
7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477
	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");
	}
	if (distinct && test_all_bits(used_tables,thd->used_tables))
	  buff_ptr= strmov(buff_ptr,"; Distinct");
	if (buff_ptr == buff)
	  buff_ptr+= 2;
	item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2));
unknown's avatar
unknown committed
7478 7479 7480
      }
      // For next iteration
      used_tables|=table->map;
7481 7482
      if (result->send_data(item_list))
	result->send_error(0,NullS);
unknown's avatar
unknown committed
7483
    }
unknown's avatar
unknown committed
7484
  }
7485
  if (!thd->lex.select->next)			// Not union
7486 7487 7488 7489 7490 7491
  {
    save_lock=thd->lock;
    thd->lock=(MYSQL_LOCK *)0;
    result->send_eof();
    thd->lock=save_lock;
  }
unknown's avatar
unknown committed
7492 7493 7494 7495
  DBUG_VOID_RETURN;
}


7496
static void describe_info(JOIN *join, const char *info)
unknown's avatar
unknown committed
7497
{
7498 7499 7500 7501 7502
  THD *thd= join->thd;

  if (thd->lex.select_lex.next)			/* If in UNION */
  {
    select_describe(join,FALSE,FALSE,FALSE,info);
unknown's avatar
unknown committed
7503
    return;
7504
  }
unknown's avatar
unknown committed
7505 7506 7507
  List<Item> field_list;
  String *packet= &thd->packet;

7508
  /* Don't log this into the slow query log */
7509 7510
  thd->lex.select_lex.options&= ~(QUERY_NO_INDEX_USED |
				  QUERY_NO_GOOD_INDEX_USED);
unknown's avatar
unknown committed
7511 7512
  field_list.push_back(new Item_empty_string("Comment",80));
  if (send_fields(thd,field_list,1))
unknown's avatar
unknown committed
7513
    return; /* purecov: inspected */
unknown's avatar
unknown committed
7514 7515 7516 7517 7518
  packet->length(0);
  net_store_data(packet,info);
  if (!my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
    send_eof(&thd->net);
}