sql_union.cc 20.5 KB
Newer Older
1
/* Copyright (C) 2000-2003 MySQL AB
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2 3 4

   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
5
   the Free Software Foundation; version 2 of the License.
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

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


/*
  UNION  of select's
  UNION's  were introduced by Monty and Sinisa <sinisa@mysql.com>
*/


#include "mysql_priv.h"
#include "sql_select.h"
25
#include "sql_cursor.h"
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
26

27
bool mysql_union(THD *thd, LEX *lex, select_result *result,
28
                 SELECT_LEX_UNIT *unit, ulong setup_tables_done_option)
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
29 30
{
  DBUG_ENTER("mysql_union");
31
  bool res;
32
  if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK |
33
                           setup_tables_done_option)))
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
34
    res= unit->exec();
35
  if (res || !thd->cursor || !thd->cursor->is_open())
36 37
    res|= unit->cleanup();
  DBUG_RETURN(res);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
38 39 40 41 42 43 44 45 46 47 48 49 50
}


/***************************************************************************
** store records in temporary table for UNION
***************************************************************************/

int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
  unit= u;
  return 0;
}

51

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
52 53
bool select_union::send_data(List<Item> &values)
{
54
  int error= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
55 56 57 58 59
  if (unit->offset_limit_cnt)
  {						// using limit offset,count
    unit->offset_limit_cnt--;
    return 0;
  }
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
60
  fill_record(thd, table->field, values, 1);
61 62 63
  if (thd->net.report_error)
    return 1;

64
  if ((error= table->file->ha_write_row(table->record[0])))
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
65
  {
66
    /* create_myisam_from_heap will generate error if needed */
67
    if (table->file->is_fatal_error(error, HA_CHECK_DUP) &&
68
        create_myisam_from_heap(thd, table, &tmp_table_param, error, 1))
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
69 70 71 72 73
      return 1;
  }
  return 0;
}

74

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
75 76 77 78
bool select_union::send_eof()
{
  return 0;
}
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
79

80

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
81
bool select_union::flush()
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
82
{
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
83 84 85
  int error;
  if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
  {
86
    table->file->print_error(error, MYF(0));
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
87 88 89 90 91
    return 1;
  }
  return 0;
}

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
/*
  Create a temporary table to store the result of select_union.

  SYNOPSIS
    select_union::create_result_table()
      thd                thread handle
      column_types       a list of items used to define columns of the
                         temporary table
      is_union_distinct  if set, the temporary table will eliminate
                         duplicates on insert
      options            create options

  DESCRIPTION
    Create a temporary table that is used to store the result of a UNION,
    derived table, or a materialized cursor.

  RETURN VALUE
    0                    The table has been created successfully.
    1                    create_tmp_table failed.
*/

bool
114
select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
115 116 117 118 119 120 121
                                  bool is_union_distinct, ulonglong options,
                                  const char *alias)
{
  DBUG_ASSERT(table == 0);
  tmp_table_param.init();
  tmp_table_param.field_count= column_types->elements;

122
  if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
123 124 125 126 127 128 129 130
                                 (ORDER*) 0, is_union_distinct, 1,
                                 options, HA_POS_ERROR, (char*) alias)))
    return TRUE;
  table->file->extra(HA_EXTRA_WRITE_CACHE);
  table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
  return FALSE;
}

131

132 133 134 135 136 137 138 139 140 141 142
/*
  initialization procedures before fake_select_lex preparation()

  SYNOPSIS
    st_select_lex_unit::init_prepare_fake_select_lex()
    thd		- thread handler

  RETURN
    options of SELECT
*/

143
void
144
st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg) 
145
{
146
  thd_arg->lex->current_select= fake_select_lex;
147 148
  fake_select_lex->table_list.link_in_list((byte *)&result_table_list,
					   (byte **)
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
149
					   &result_table_list.next_local);
150 151
  fake_select_lex->context.table_list= fake_select_lex->context.first_name_resolution_table= 
    fake_select_lex->get_table_list();
152 153 154 155
  for (ORDER *order= (ORDER *)global_parameters->order_list.first;
       order;
       order=order->next)
  {
156 157
    (*order->item)->walk(&Item::change_context_processor, 0,
                         (byte*) &fake_select_lex->context);
158
  }
159 160 161
}


162
bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
163
                                 ulong additional_options)
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
164
{
165
  SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
166
  SELECT_LEX *sl, *first_sl= first_select();
167
  select_result *tmp_result;
168
  bool is_union;
169
  TABLE *empty_table= 0;
170 171
  DBUG_ENTER("st_select_lex_unit::prepare");

172 173
  describe= test(additional_options & SELECT_DESCRIBE);

174 175 176 177 178 179
  /*
    result object should be reassigned even if preparing already done for
    max/min subquery (ALL/ANY optimization)
  */
  result= sel_result;

180
  if (prepared)
181 182 183 184
  {
    if (describe)
    {
      /* fast reinit for EXPLAIN */
185
      for (sl= first_sl; sl; sl= sl->next_select())
186 187 188 189 190 191 192
      {
	sl->join->result= result;
	select_limit_cnt= HA_POS_ERROR;
	offset_limit_cnt= 0;
	if (!sl->join->procedure &&
	    result->prepare(sl->join->fields_list, this))
	{
193
	  DBUG_RETURN(TRUE);
194 195 196 197 198
	}
	sl->join->select_options|= SELECT_DESCRIBE;
	sl->join->reinit();
      }
    }
199
    DBUG_RETURN(FALSE);
200
  }
201
  prepared= 1;
202
  saved_error= FALSE;
203
  
204 205
  thd_arg->lex->current_select= sl= first_sl;
  found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
206
  is_union= first_sl->next_select() || fake_select_lex;
207

208
  /* Global option */
209

210
  if (is_union)
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
211
  {
212
    if (!(tmp_result= union_result= new select_union))
213
      goto err;
214 215
    if (describe)
      tmp_result= sel_result;
216 217
  }
  else
218
    tmp_result= sel_result;
219

220 221
  sl->context.resolve_in_select_list= TRUE;

222
  for (;sl; sl= sl->next_select())
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
223
  {
224
    bool can_skip_order_by;
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
225
    sl->options|=  SELECT_NO_UNLOCK;
226
    JOIN *join= new JOIN(thd_arg, sl->item_list, 
227
			 sl->options | thd_arg->options | additional_options,
228
			 tmp_result);
229 230 231 232 233 234 235
    /*
      setup_tables_done_option should be set only for very first SELECT,
      because it protect from secont setup_tables call for select-like non
      select commands (DELETE/INSERT/...) and they use only very first
      SELECT (for union it can be only INSERT ... SELECT).
    */
    additional_options&= ~OPTION_SETUP_TABLES_DONE;
monty@mysql.com's avatar
monty@mysql.com committed
236 237 238
    if (!join)
      goto err;

239
    thd_arg->lex->current_select= sl;
240

241 242
    can_skip_order_by= is_union && !(sl->braces && sl->explicit_limit);

243 244 245 246 247 248 249 250 251 252 253 254 255 256
    saved_error= join->prepare(&sl->ref_pointer_array,
                               (TABLE_LIST*) sl->table_list.first,
                               sl->with_wild,
                               sl->where,
                               (can_skip_order_by ? 0 :
                                sl->order_list.elements) +
                               sl->group_list.elements,
                               can_skip_order_by ?
                               (ORDER*) 0 : (ORDER *)sl->order_list.first,
                               (ORDER*) sl->group_list.first,
                               sl->having,
                               (is_union ? (ORDER*) 0 :
                                (ORDER*) thd_arg->lex->proc_list.first),
                               sl, this);
257 258 259
    /* There are no * in the statement anymore (for PS) */
    sl->with_wild= 0;
    last_procedure= join->procedure;
monty@mysql.com's avatar
monty@mysql.com committed
260

261
    if (saved_error || (saved_error= thd_arg->is_fatal_error))
262
      goto err;
263 264 265 266 267
    /*
      Use items list of underlaid select for derived tables to preserve
      information about fields lengths and exact types
    */
    if (!is_union)
268 269
      types= first_sl->item_list;
    else if (sl == first_sl)
270
    {
271 272 273 274 275 276 277 278
      /*
        We need to create an empty table object. It is used
        to create tmp_table fields in Item_type_holder.
        The main reason of this is that we can't create
        field object without table.
      */
      DBUG_ASSERT(!empty_table);
      empty_table= (TABLE*) thd->calloc(sizeof(TABLE));
279 280
      types.empty();
      List_iterator_fast<Item> it(sl->item_list);
281 282
      Item *item_tmp;
      while ((item_tmp= it++))
283
      {
monty@mysql.com's avatar
monty@mysql.com committed
284
	/* Error's in 'new' will be detected after loop */
285
	types.push_back(new Item_type_holder(thd_arg, item_tmp));
286 287
      }

288
      if (thd_arg->is_fatal_error)
289 290 291 292 293 294 295 296 297 298 299 300
	goto err; // out of memory
    }
    else
    {
      if (types.elements != sl->item_list.elements)
      {
	my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
		   ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
	goto err;
      }
      List_iterator_fast<Item> it(sl->item_list);
      List_iterator_fast<Item> tp(types);	
301 302
      Item *type, *item_tmp;
      while ((type= tp++, item_tmp= it++))
303
      {
304
        if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
305
	  DBUG_RETURN(TRUE);
306 307
      }
    }
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
308
  }
309

310
  if (is_union)
311
  {
312
    /*
bar@mysql.com's avatar
bar@mysql.com committed
313 314
      Check that it was possible to aggregate
      all collations together for UNION.
315 316 317
    */
    List_iterator_fast<Item> tp(types);
    Item *type;
318
    ulonglong create_options;
monty@mysql.com's avatar
monty@mysql.com committed
319

320 321 322 323 324 325 326 327 328
    while ((type= tp++))
    {
      if (type->result_type() == STRING_RESULT &&
          type->collation.derivation == DERIVATION_NONE)
      {
        my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), "UNION");
        goto err;
      }
    }
329
    
330
    create_options= (first_sl->options | thd_arg->options |
331
                     TMP_TABLE_ALL_COLUMNS);
332 333 334
    /*
      Force the temporary table to be a MyISAM table if we're going to use
      fullext functions (MATCH ... AGAINST .. IN BOOLEAN MODE) when reading
335 336
      from it (this should be removed in 5.2 when fulltext search is moved 
      out of MyISAM).
337 338 339
    */
    if (global_parameters->ftfunc_list->elements)
      create_options= create_options | TMP_TABLE_FORCE_MYISAM;
340

341 342
    if (union_result->create_result_table(thd, &types, test(union_distinct),
                                          create_options, ""))
343 344 345
      goto err;
    bzero((char*) &result_table_list, sizeof(result_table_list));
    result_table_list.db= (char*) "";
346
    result_table_list.table_name= result_table_list.alias= (char*) "union";
347
    result_table_list.table= table= union_result->table;
348

349
    thd_arg->lex->current_select= lex_select_save;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
350
    if (!item_list.elements)
351
    {
352
      Query_arena *arena, backup_arena;
353

354 355
      arena= thd->activate_stmt_arena_if_needed(&backup_arena);
      
356
      saved_error= table->fill_item_list(&item_list);
357 358 359 360

      if (arena)
        thd->restore_active_arena(arena, &backup_arena);

361
      if (saved_error)
362 363 364
        goto err;

      if (thd->stmt_arena->is_stmt_prepare())
365
      {
366 367
        /* Validate the global parameters of this union */

368
	init_prepare_fake_select_lex(thd);
369
        /* Should be done only once (the only item_list per statement) */
370
        DBUG_ASSERT(fake_select_lex->join == 0);
371 372 373 374
	if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options,
					      result)))
	{
	  fake_select_lex->table_list.empty();
375
	  DBUG_RETURN(TRUE);
376 377 378 379
	}
	fake_select_lex->item_list= item_list;

	thd_arg->lex->current_select= fake_select_lex;
380
	saved_error= fake_select_lex->join->
381 382 383 384 385
	  prepare(&fake_select_lex->ref_pointer_array,
		  (TABLE_LIST*) fake_select_lex->table_list.first,
		  0, 0,
		  fake_select_lex->order_list.elements,
		  (ORDER*) fake_select_lex->order_list.first,
386 387
		  (ORDER*) NULL, NULL,
                  (ORDER*) NULL,
388 389 390
		  fake_select_lex, this);
	fake_select_lex->table_list.empty();
      }
391
    }
392
    else
393
    {
394
      DBUG_ASSERT(!thd->stmt_arena->is_conventional());
395
      /*
monty@mysql.com's avatar
monty@mysql.com committed
396 397
        We're in execution of a prepared statement or stored procedure:
        reset field items to point at fields from the created temporary table.
398
      */
399
      table->reset_item_list(&item_list);
400
    }
401
  }
402

403
  thd_arg->lex->current_select= lex_select_save;
404

405
  DBUG_RETURN(saved_error || thd_arg->is_fatal_error);
406

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
407
err:
408
  thd_arg->lex->current_select= lex_select_save;
409
  DBUG_RETURN(TRUE);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
410 411
}

412

413
bool st_select_lex_unit::exec()
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
414
{
415
  SELECT_LEX *lex_select_save= thd->lex->current_select;
416
  SELECT_LEX *select_cursor=first_select();
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
417
  ulonglong add_rows=0;
418
  ha_rows examined_rows= 0;
419 420
  DBUG_ENTER("st_select_lex_unit::exec");

421
  if (executed && !uncacheable && !describe)
422
    DBUG_RETURN(FALSE);
423 424
  executed= 1;
  
425
  if (uncacheable || !item || !item->assigned() || describe)
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
426
  {
427 428
    if (item)
      item->reset_value_registration();
429
    if (optimized && item)
430
    {
431 432 433 434 435 436 437 438
      if (item->assigned())
      {
        item->assigned(0); // We will reinit & rexecute unit
        item->reset();
        table->file->delete_all_rows();
      }
      /* re-enabling indexes for next subselect iteration */
      if (union_distinct && table->file->enable_indexes(HA_KEY_SWITCH_ALL))
439
      {
serg@serg.mylan's avatar
serg@serg.mylan committed
440
        DBUG_ASSERT(0);
441
      }
442
    }
443
    for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
444
    {
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
445
      ha_rows records_at_start= 0;
446
      thd->lex->current_select= sl;
447

448
      if (optimized)
449
	saved_error= sl->join->reinit();
450 451
      else
      {
452 453
        set_limit(sl);
	if (sl == global_parameters || describe)
454 455 456 457 458 459
	{
	  offset_limit_cnt= 0;
	  /*
	    We can't use LIMIT at this stage if we are using ORDER BY for the
	    whole query
	  */
460
	  if (sl->order_list.first || describe)
461
	    select_limit_cnt= HA_POS_ERROR;
462
        }
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
463

464 465 466 467 468 469 470 471
        /*
          When using braces, SQL_CALC_FOUND_ROWS affects the whole query:
          we don't calculate found_rows() per union part.
          Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
        */
        sl->join->select_options= 
          (select_limit_cnt == HA_POS_ERROR || sl->braces) ?
          sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
472
	saved_error= sl->join->optimize();
473
      }
474
      if (!saved_error)
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
475
      {
476
	records_at_start= table->file->stats.records;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
477
	sl->join->exec();
478
        if (sl == union_distinct)
479 480
	{
	  if (table->file->disable_indexes(HA_KEY_SWITCH_ALL))
481
	    DBUG_RETURN(TRUE);
482 483
	  table->no_keyread=1;
	}
484
	saved_error= sl->join->error;
485 486 487
	offset_limit_cnt= (ha_rows)(sl->offset_limit ?
                                    sl->offset_limit->val_uint() :
                                    0);
488
	if (!saved_error)
489
	{
490 491 492 493 494 495
	  examined_rows+= thd->examined_row_count;
	  if (union_result->flush())
	  {
	    thd->lex->current_select= lex_select_save;
	    DBUG_RETURN(1);
	  }
496
	}
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
497
      }
498
      if (saved_error)
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
499
      {
500
	thd->lex->current_select= lex_select_save;
501
	DBUG_RETURN(saved_error);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
502
      }
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
503
      /* Needed for the following test and for records_at_start in next loop */
504 505 506 507 508 509
      int error= table->file->info(HA_STATUS_VARIABLE);
      if(error)
      {
        table->file->print_error(error, MYF(0));
        DBUG_RETURN(1);
      }
510 511
      if (found_rows_for_union && !sl->braces && 
          select_limit_cnt != HA_POS_ERROR)
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
512 513
      {
	/*
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
514 515
	  This is a union without braces. Remember the number of rows that
	  could also have been part of the result set.
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
516 517 518
	  We get this from the difference of between total number of possible
	  rows and actual rows added to the temporary table.
	*/
519
	add_rows+= (ulonglong) (thd->limit_found_rows - (ulonglong)
520
			      ((table->file->stats.records -  records_at_start)));
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
521
      }
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
522
    }
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
523
  }
524
  optimized= 1;
525 526

  /* Send result to 'result' */
527
  saved_error= TRUE;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
528
  {
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
529 530
    List<Item_func_match> empty_list;
    empty_list.empty();
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
531

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
532
    if (!thd->is_fatal_error)				// Check if EOM
533
    {
534 535
      set_limit(global_parameters);
      init_prepare_fake_select_lex(thd);
536 537 538 539
      JOIN *join= fake_select_lex->join;
      if (!join)
      {
	/*
monty@mysql.com's avatar
monty@mysql.com committed
540
	  allocate JOIN for fake select only once (prevent
541 542
	  mysql_select automatic allocation)
	*/
pem@mysql.com's avatar
pem@mysql.com committed
543 544
	if (!(fake_select_lex->join= new JOIN(thd, item_list,
					      fake_select_lex->options, result)))
545 546
	{
	  fake_select_lex->table_list.empty();
547
	  DBUG_RETURN(TRUE);
548
	}
monty@mysql.com's avatar
monty@mysql.com committed
549

550 551 552 553 554
	/*
	  Fake st_select_lex should have item list for correctref_array
	  allocation.
	*/
	fake_select_lex->item_list= item_list;
555 556 557 558
      }
      else
      {
	JOIN_TAB *tab,*end;
559 560 561
	for (tab=join->join_tab, end=tab+join->tables ;
	     tab && tab != end ;
	     tab++)
562 563 564 565
	{
	  delete tab->select;
	  delete tab->quick;
	}
566
	join->init(thd, item_list, fake_select_lex->options, result);
567
      }
568 569 570 571 572 573 574 575
      saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
                            &result_table_list,
                            0, item_list, NULL,
                            global_parameters->order_list.elements,
                            (ORDER*)global_parameters->order_list.first,
                            (ORDER*) NULL, NULL, (ORDER*) NULL,
                            fake_select_lex->options | SELECT_NO_UNLOCK,
                            result, this, fake_select_lex);
576 577

      fake_select_lex->table_list.empty();
578
      if (!saved_error)
579
      {
580
	thd->limit_found_rows = (ulonglong)table->file->stats.records + add_rows;
581
        thd->examined_row_count+= examined_rows;
582
      }
583 584 585 586
      /*
	Mark for slow query log if any of the union parts didn't use
	indexes efficiently
      */
587
    }
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
588
  }
589
  thd->lex->current_select= lex_select_save;
590
  DBUG_RETURN(saved_error);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
591 592
}

593

594
bool st_select_lex_unit::cleanup()
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
595
{
596
  int error= 0;
597
  DBUG_ENTER("st_select_lex_unit::cleanup");
598

599 600
  if (cleaned)
  {
601
    DBUG_RETURN(FALSE);
602
  }
603
  cleaned= 1;
604

605 606 607
  if (union_result)
  {
    delete union_result;
608
    union_result=0; // Safety
609 610
    if (table)
      free_tmp_table(thd, table);
611 612
    table= 0; // Safety
  }
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
613

614
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
615 616 617
    error|= sl->cleanup();

  if (fake_select_lex)
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
618
  {
619 620
    JOIN *join;
    if ((join= fake_select_lex->join))
621
    {
622 623
      join->tables_list= 0;
      join->tables= 0;
624
    }
625
    error|= fake_select_lex->cleanup();
626 627 628 629 630 631
    if (fake_select_lex->order_list.elements)
    {
      ORDER *ord;
      for (ord= (ORDER*)fake_select_lex->order_list.first; ord; ord= ord->next)
        (*ord->item)->cleanup();
    }
632
  }
bell@sanja.is.com.ua's avatar
VIEW  
bell@sanja.is.com.ua committed
633

634
  DBUG_RETURN(error);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
635
}
636 637 638 639 640


void st_select_lex_unit::reinit_exec_mechanism()
{
  prepared= optimized= executed= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
641
#ifndef DBUG_OFF
642
  if (first_select()->next_select())
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
643
  {
644 645 646 647 648 649 650 651 652 653 654
    List_iterator_fast<Item> it(item_list);
    Item *field;
    while ((field= it++))
    {
      /*
	we can't cleanup here, because it broke link to temporary table field,
	but have to drop fixed flag to allow next fix_field of this field
	during re-executing
      */
      field->fixed= 0;
    }
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
655 656
  }
#endif
657
}
658 659 660 661 662 663 664 665 666 667 668


/*
  change select_result object of unit

  SYNOPSIS
    st_select_lex_unit::change_result()
    result	new select_result object
    old_result	old select_result object

  RETURN
669 670
    FALSE - OK
    TRUE  - error
671 672
*/

673
bool st_select_lex_unit::change_result(select_subselect *new_result,
674
                                       select_subselect *old_result)
675
{
676
  bool res= FALSE;
677
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
678 679
  {
    if (sl->join && sl->join->result == old_result)
680
      if (sl->join->change_result(new_result))
681
	return TRUE;
682 683
  }
  if (fake_select_lex && fake_select_lex->join)
684
    res= fake_select_lex->join->change_result(new_result);
685 686
  return (res);
}
687

688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
/*
  Get column type information for this unit.

  SYNOPSIS
    st_select_lex_unit::get_unit_column_types()

  DESCRIPTION
    For a single-select the column types are taken
    from the list of selected items. For a union this function
    assumes that st_select_lex_unit::prepare has been called
    and returns the type holders that were created for unioned
    column types of all selects.

  NOTES
    The implementation of this function should be in sync with
    st_select_lex_unit::prepare()
*/

List<Item> *st_select_lex_unit::get_unit_column_types()
{
708 709 710 711 712 713 714 715 716 717 718
  SELECT_LEX *sl= first_select();
  bool is_union= test(sl->next_select());
  bool is_procedure= test(sl->join->procedure);

  if (is_procedure)
  {
    /* Types for "SELECT * FROM t1 procedure analyse()"
       are generated during execute */
    return &sl->join->procedure_fields_list;
  }

719 720 721 722 723 724 725

  if (is_union)
  {
    DBUG_ASSERT(prepared);
    /* Types are generated during prepare */
    return &types;
  }
726 727

  return &sl->item_list;
728
}
729 730 731 732 733 734 735 736

bool st_select_lex::cleanup()
{
  bool error= FALSE;
  DBUG_ENTER("st_select_lex::cleanup()");

  if (join)
  {
737
    DBUG_ASSERT((st_select_lex*)join->select_lex == this);
738
    error= join->destroy();
739 740 741 742 743 744
    delete join;
    join= 0;
  }
  for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ;
       lex_unit= lex_unit->next_unit())
  {
745
    error= (bool) ((uint) error | (uint) lex_unit->cleanup());
746
  }
747
  non_agg_fields.empty();
748 749 750
  DBUG_RETURN(error);
}

751 752 753 754 755 756 757 758 759 760 761 762 763

void st_select_lex::cleanup_all_joins(bool full)
{
  SELECT_LEX_UNIT *unit;
  SELECT_LEX *sl;

  if (join)
    join->cleanup(full);

  for (unit= first_inner_unit(); unit; unit= unit->next_unit())
    for (sl= unit->first_select(); sl; sl= sl->next_select())
      sl->cleanup_all_joins(full);
}