sql_union.cc 20.5 KB
Newer Older
1
/* Copyright (C) 2000-2003 MySQL AB
unknown's avatar
unknown 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
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown 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"
unknown's avatar
unknown committed
26

unknown's avatar
unknown committed
27
bool mysql_union(THD *thd, LEX *lex, select_result *result,
28
                 SELECT_LEX_UNIT *unit, ulong setup_tables_done_option)
unknown's avatar
unknown committed
29 30
{
  DBUG_ENTER("mysql_union");
unknown's avatar
unknown committed
31
  bool res;
32
  if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK |
33
                           setup_tables_done_option)))
unknown's avatar
unknown committed
34
    res= unit->exec();
35
  if (res || !thd->cursor || !thd->cursor->is_open())
unknown's avatar
unknown committed
36 37
    res|= unit->cleanup();
  DBUG_RETURN(res);
unknown's avatar
unknown 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

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

  if ((error= table->file->write_row(table->record[0])))
unknown's avatar
unknown committed
65
  {
66 67 68
    /* create_myisam_from_heap will generate error if needed */
    if (error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE &&
        create_myisam_from_heap(thd, table, &tmp_table_param, error, 1))
unknown's avatar
unknown committed
69 70 71 72 73
      return 1;
  }
  return 0;
}

74

unknown's avatar
unknown committed
75 76 77 78
bool select_union::send_eof()
{
  return 0;
}
unknown's avatar
unknown committed
79

80

unknown's avatar
unknown committed
81
bool select_union::flush()
unknown's avatar
unknown committed
82
{
unknown's avatar
unknown committed
83 84 85
  int error;
  if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
  {
unknown's avatar
unknown committed
86
    table->file->print_error(error, MYF(0));
unknown's avatar
unknown 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 **)
unknown's avatar
VIEW  
unknown 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 156 157 158
  for (ORDER *order= (ORDER *)global_parameters->order_list.first;
       order;
       order=order->next)
  {
    (*order->item)->walk(&Item::change_context_processor,
                         (byte *) &fake_select_lex->context);
  }
159 160 161
}


unknown's avatar
unknown committed
162
bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
163
                                 ulong additional_options)
unknown's avatar
unknown 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;
unknown's avatar
unknown committed
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;

unknown's avatar
unknown committed
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))
	{
unknown's avatar
unknown committed
193
	  DBUG_RETURN(TRUE);
194 195 196 197 198
	}
	sl->join->select_options|= SELECT_DESCRIBE;
	sl->join->reinit();
      }
    }
unknown's avatar
unknown committed
199
    DBUG_RETURN(FALSE);
200
  }
unknown's avatar
unknown committed
201
  prepared= 1;
202
  saved_error= FALSE;
unknown's avatar
unknown committed
203
  
204 205
  thd_arg->lex->current_select= sl= first_sl;
  found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
unknown's avatar
unknown committed
206
  is_union= first_sl->next_select() || fake_select_lex;
207

208
  /* Global option */
209

210
  if (is_union)
unknown's avatar
unknown 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;
unknown's avatar
unknown committed
219

220 221
  sl->context.resolve_in_select_list= TRUE;

222
  for (;sl; sl= sl->next_select())
unknown's avatar
unknown committed
223
  {
224
    bool can_skip_order_by;
unknown's avatar
unknown 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;
unknown's avatar
unknown committed
236 237 238
    if (!join)
      goto err;

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

unknown's avatar
unknown committed
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;
unknown's avatar
unknown 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
      {
unknown's avatar
unknown 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))
unknown's avatar
unknown committed
305
	  DBUG_RETURN(TRUE);
306 307
      }
    }
unknown's avatar
unknown committed
308
  }
309

310
  if (is_union)
311
  {
312
    /*
unknown's avatar
unknown 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;
unknown's avatar
unknown 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;
unknown's avatar
unknown 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();
unknown's avatar
unknown committed
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
      /*
unknown's avatar
unknown 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

unknown's avatar
unknown committed
407
err:
408
  thd_arg->lex->current_select= lex_select_save;
unknown's avatar
unknown committed
409
  DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
410 411
}

412

unknown's avatar
unknown committed
413
bool st_select_lex_unit::exec()
unknown's avatar
unknown committed
414
{
415
  SELECT_LEX *lex_select_save= thd->lex->current_select;
416
  SELECT_LEX *select_cursor=first_select();
unknown's avatar
unknown committed
417
  ulonglong add_rows=0;
unknown's avatar
unknown committed
418
  ha_rows examined_rows= 0;
419 420
  DBUG_ENTER("st_select_lex_unit::exec");

421
  if (executed && !uncacheable && !describe)
unknown's avatar
unknown committed
422
    DBUG_RETURN(FALSE);
unknown's avatar
unknown committed
423 424
  executed= 1;
  
425
  if (uncacheable || !item || !item->assigned() || describe)
unknown's avatar
unknown committed
426
  {
427 428
    if (item)
      item->reset_value_registration();
429
    if (optimized && item)
unknown's avatar
unknown committed
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))
unknown's avatar
unknown committed
439
        DBUG_ASSERT(0);
unknown's avatar
unknown committed
440
    }
441
    for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
unknown's avatar
unknown committed
442
    {
unknown's avatar
unknown committed
443
      ha_rows records_at_start= 0;
444
      thd->lex->current_select= sl;
445

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

462 463 464 465 466 467 468 469
        /*
          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;
470
	saved_error= sl->join->optimize();
unknown's avatar
unknown committed
471
      }
472
      if (!saved_error)
unknown's avatar
unknown committed
473
      {
unknown's avatar
unknown committed
474
	records_at_start= table->file->records;
unknown's avatar
unknown committed
475
	sl->join->exec();
476
        if (sl == union_distinct)
unknown's avatar
unknown committed
477 478
	{
	  if (table->file->disable_indexes(HA_KEY_SWITCH_ALL))
unknown's avatar
unknown committed
479
	    DBUG_RETURN(TRUE);
unknown's avatar
unknown committed
480 481
	  table->no_keyread=1;
	}
482
	saved_error= sl->join->error;
483 484 485
	offset_limit_cnt= (ha_rows)(sl->offset_limit ?
                                    sl->offset_limit->val_uint() :
                                    0);
486
	if (!saved_error)
unknown's avatar
unknown committed
487
	{
488 489 490 491 492 493
	  examined_rows+= thd->examined_row_count;
	  if (union_result->flush())
	  {
	    thd->lex->current_select= lex_select_save;
	    DBUG_RETURN(1);
	  }
unknown's avatar
unknown committed
494
	}
unknown's avatar
unknown committed
495
      }
496
      if (saved_error)
unknown's avatar
unknown committed
497
      {
498
	thd->lex->current_select= lex_select_save;
499
	DBUG_RETURN(saved_error);
unknown's avatar
unknown committed
500
      }
unknown's avatar
unknown committed
501
      /* Needed for the following test and for records_at_start in next loop */
502 503 504 505 506 507
      int error= table->file->info(HA_STATUS_VARIABLE);
      if(error)
      {
        table->file->print_error(error, MYF(0));
        DBUG_RETURN(1);
      }
508 509
      if (found_rows_for_union && !sl->braces && 
          select_limit_cnt != HA_POS_ERROR)
unknown's avatar
unknown committed
510 511
      {
	/*
unknown's avatar
unknown committed
512 513
	  This is a union without braces. Remember the number of rows that
	  could also have been part of the result set.
unknown's avatar
unknown committed
514 515 516
	  We get this from the difference of between total number of possible
	  rows and actual rows added to the temporary table.
	*/
517
	add_rows+= (ulonglong) (thd->limit_found_rows - (ulonglong)
unknown's avatar
unknown committed
518
			      ((table->file->records -  records_at_start)));
unknown's avatar
unknown committed
519
      }
unknown's avatar
unknown committed
520
    }
unknown's avatar
unknown committed
521
  }
unknown's avatar
unknown committed
522
  optimized= 1;
523 524

  /* Send result to 'result' */
525
  saved_error= TRUE;
unknown's avatar
unknown committed
526
  {
unknown's avatar
unknown committed
527 528
    List<Item_func_match> empty_list;
    empty_list.empty();
unknown's avatar
unknown committed
529

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

unknown's avatar
unknown committed
548 549 550 551 552
	/*
	  Fake st_select_lex should have item list for correctref_array
	  allocation.
	*/
	fake_select_lex->item_list= item_list;
553 554 555 556
      }
      else
      {
	JOIN_TAB *tab,*end;
557 558 559
	for (tab=join->join_tab, end=tab+join->tables ;
	     tab && tab != end ;
	     tab++)
560 561 562 563
	{
	  delete tab->select;
	  delete tab->quick;
	}
564
	join->init(thd, item_list, fake_select_lex->options, result);
565
      }
566 567 568 569 570 571 572 573
      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);
574 575

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

591

unknown's avatar
unknown committed
592
bool st_select_lex_unit::cleanup()
unknown's avatar
unknown committed
593
{
594
  int error= 0;
595
  DBUG_ENTER("st_select_lex_unit::cleanup");
596

597 598
  if (cleaned)
  {
unknown's avatar
unknown committed
599
    DBUG_RETURN(FALSE);
600
  }
601
  cleaned= 1;
602

unknown's avatar
unknown committed
603 604 605
  if (union_result)
  {
    delete union_result;
unknown's avatar
unknown committed
606
    union_result=0; // Safety
607 608
    if (table)
      free_tmp_table(thd, table);
unknown's avatar
unknown committed
609 610
    table= 0; // Safety
  }
unknown's avatar
VIEW  
unknown committed
611

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

  if (fake_select_lex)
unknown's avatar
unknown committed
616
  {
617 618
    JOIN *join;
    if ((join= fake_select_lex->join))
619
    {
620 621
      join->tables_list= 0;
      join->tables= 0;
622
    }
623
    error|= fake_select_lex->cleanup();
624 625 626 627 628 629
    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();
    }
630
  }
unknown's avatar
VIEW  
unknown committed
631

632
  DBUG_RETURN(error);
unknown's avatar
unknown committed
633
}
unknown's avatar
unknown committed
634 635 636 637 638


void st_select_lex_unit::reinit_exec_mechanism()
{
  prepared= optimized= executed= 0;
unknown's avatar
unknown committed
639
#ifndef DBUG_OFF
640
  if (first_select()->next_select())
unknown's avatar
unknown committed
641
  {
642 643 644 645 646 647 648 649 650 651 652
    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;
    }
unknown's avatar
unknown committed
653 654
  }
#endif
unknown's avatar
unknown committed
655
}
656 657 658 659 660 661 662 663 664 665 666


/*
  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
unknown's avatar
unknown committed
667 668
    FALSE - OK
    TRUE  - error
669 670
*/

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

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
/*
  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()
{
706 707 708 709 710 711 712 713 714 715 716
  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;
  }

717 718 719 720 721 722 723

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

  return &sl->item_list;
726
}
727 728 729 730 731 732 733 734

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

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

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

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