~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2003 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
17
/*
18
  UNION  of select's
19
  UNION's  were introduced by Monty and Sinisa <sinisa@mysql.com>
20
*/
21
22
23
#include "mysql_priv.h"
24
#include "sql_select.h"
25
26
bool mysql_union(THD *thd, LEX *lex, select_result *result,
27
                 SELECT_LEX_UNIT *unit, ulong setup_tables_done_option)
28
{
29
  DBUG_ENTER("mysql_union");
30
  bool res;
31
  if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK |
32
                           setup_tables_done_option)))
33
    res= unit->exec();
34
  if (res)
35
    res|= unit->cleanup();
36
  DBUG_RETURN(res);
37
}
38
39
40
/***************************************************************************
41
** store records in temporary table for UNION
42
***************************************************************************/
43
44
int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
45
{
46
  unit= u;
47
  return 0;
48
}
49
50
51
bool select_union::send_data(List<Item> &values)
52
{
53
  int error= 0;
54
  if (unit->offset_limit_cnt)
55
  {						// using limit offset,count
56
    unit->offset_limit_cnt--;
57
    return 0;
58
  }
59
  fill_record(thd, table->field, values, 1);
60
  if (thd->is_error())
61
    return 1;
62
63
  if ((error= table->file->ha_write_row(table->record[0])))
64
  {
65
    /* create_myisam_from_heap will generate error if needed */
66
    if (table->file->is_fatal_error(error, HA_CHECK_DUP) &&
67
        create_myisam_from_heap(thd, table, tmp_table_param.start_recinfo, 
68
                                &tmp_table_param.recinfo, error, 1))
69
      return 1;
70
  }
71
  return 0;
72
}
73
74
75
bool select_union::send_eof()
76
{
77
  return 0;
78
}
79
80
81
bool select_union::flush()
82
{
83
  int error;
84
  if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
85
  {
86
    table->file->print_error(error, MYF(0));
87
    return 1;
88
  }
89
  return 0;
90
}
91
92
/*
93
  Create a temporary table to store the result of select_union.
94
95
  SYNOPSIS
96
    select_union::create_result_table()
97
      thd                thread handle
98
      column_types       a list of items used to define columns of the
99
                         temporary table
100
      is_union_distinct  if set, the temporary table will eliminate
101
                         duplicates on insert
102
      options            create options
103
      table_alias        name of the temporary table
104
      bit_fields_as_long convert bit fields to ulonglong
105
106
  DESCRIPTION
107
    Create a temporary table that is used to store the result of a UNION,
108
    derived table, or a materialized cursor.
109
110
  RETURN VALUE
111
    0                    The table has been created successfully.
112
    1                    create_tmp_table failed.
113
*/
114
115
bool
116
select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
117
                                  bool is_union_distinct, ulonglong options,
118
                                  const char *table_alias,
119
                                  bool bit_fields_as_long)
120
{
121
  DBUG_ASSERT(table == 0);
122
  tmp_table_param.init();
123
  tmp_table_param.field_count= column_types->elements;
124
  tmp_table_param.bit_fields_as_long= bit_fields_as_long;
125
126
  if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
127
                                 (ORDER*) 0, is_union_distinct, 1,
128
                                 options, HA_POS_ERROR, (char*) table_alias)))
129
    return TRUE;
130
  table->file->extra(HA_EXTRA_WRITE_CACHE);
131
  table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
132
  return FALSE;
133
}
134
135
136
/**
137
  Reset and empty the temporary table that stores the materialized query result.
138
139
  @note The cleanup performed here is exactly the same as for the two temp
140
  tables of JOIN - exec_tmp_table_[1 | 2].
141
*/
142
143
void select_union::cleanup()
144
{
145
  table->file->extra(HA_EXTRA_RESET_STATE);
146
  table->file->ha_delete_all_rows();
147
  free_io_cache(table);
148
  filesort_free_buffers(table,0);
149
}
150
151
152
/*
153
  initialization procedures before fake_select_lex preparation()
154
155
  SYNOPSIS
156
    st_select_lex_unit::init_prepare_fake_select_lex()
157
    thd		- thread handler
158
159
  RETURN
160
    options of SELECT
161
*/
162
163
void
164
st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg) 
165
{
166
  thd_arg->lex->current_select= fake_select_lex;
167
  fake_select_lex->table_list.link_in_list((uchar *)&result_table_list,
168
					   (uchar **)
169
					   &result_table_list.next_local);
170
  fake_select_lex->context.table_list= 
171
    fake_select_lex->context.first_name_resolution_table= 
172
    fake_select_lex->get_table_list();
173
  if (!fake_select_lex->first_execution)
174
  {
175
    for (ORDER *order= (ORDER *) global_parameters->order_list.first;
176
         order;
177
         order= order->next)
178
      order->item= &order->item_ptr;
179
  }
180
  for (ORDER *order= (ORDER *)global_parameters->order_list.first;
181
       order;
182
       order=order->next)
183
  {
184
    (*order->item)->walk(&Item::change_context_processor, 0,
185
                         (uchar*) &fake_select_lex->context);
186
  }
187
}
188
189
190
bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
191
                                 ulong additional_options)
192
{
193
  SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
194
  SELECT_LEX *sl, *first_sl= first_select();
195
  select_result *tmp_result;
196
  bool is_union_select;
197
  TABLE *empty_table= 0;
198
  DBUG_ENTER("st_select_lex_unit::prepare");
199
200
  describe= test(additional_options & SELECT_DESCRIBE);
201
202
  /*
203
    result object should be reassigned even if preparing already done for
204
    max/min subquery (ALL/ANY optimization)
205
  */
206
  result= sel_result;
207
208
  if (prepared)
209
  {
210
    if (describe)
211
    {
212
      /* fast reinit for EXPLAIN */
213
      for (sl= first_sl; sl; sl= sl->next_select())
214
      {
215
	sl->join->result= result;
216
	select_limit_cnt= HA_POS_ERROR;
217
	offset_limit_cnt= 0;
218
	if (result->prepare(sl->join->fields_list, this))
219
	{
220
	  DBUG_RETURN(TRUE);
221
	}
222
	sl->join->select_options|= SELECT_DESCRIBE;
223
	sl->join->reinit();
224
      }
225
    }
226
    DBUG_RETURN(FALSE);
227
  }
228
  prepared= 1;
229
  saved_error= FALSE;
230
  
231
  thd_arg->lex->current_select= sl= first_sl;
232
  found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
233
  is_union_select= is_union() || fake_select_lex;
234
235
  /* Global option */
236
237
  if (is_union_select)
238
  {
239
    if (!(tmp_result= union_result= new select_union))
240
      goto err;
241
    if (describe)
242
      tmp_result= sel_result;
243
  }
244
  else
245
    tmp_result= sel_result;
246
247
  sl->context.resolve_in_select_list= TRUE;
248
249
  for (;sl; sl= sl->next_select())
250
  {
251
    bool can_skip_order_by;
252
    sl->options|=  SELECT_NO_UNLOCK;
253
    JOIN *join= new JOIN(thd_arg, sl->item_list, 
254
			 sl->options | thd_arg->options | additional_options,
255
			 tmp_result);
256
    /*
257
      setup_tables_done_option should be set only for very first SELECT,
258
      because it protect from secont setup_tables call for select-like non
259
      select commands (DELETE/INSERT/...) and they use only very first
260
      SELECT (for union it can be only INSERT ... SELECT).
261
    */
262
    additional_options&= ~OPTION_SETUP_TABLES_DONE;
263
    if (!join)
264
      goto err;
265
266
    thd_arg->lex->current_select= sl;
267
268
    can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit);
269
270
    saved_error= join->prepare(&sl->ref_pointer_array,
271
                               (TABLE_LIST*) sl->table_list.first,
272
                               sl->with_wild,
273
                               sl->where,
274
                               (can_skip_order_by ? 0 :
275
                                sl->order_list.elements) +
276
                               sl->group_list.elements,
277
                               can_skip_order_by ?
278
                               (ORDER*) 0 : (ORDER *)sl->order_list.first,
279
                               (ORDER*) sl->group_list.first,
280
                               sl->having,
281
                               (is_union_select ? (ORDER*) 0 :
282
                                (ORDER*) thd_arg->lex->proc_list.first),
283
                               sl, this);
284
    /* There are no * in the statement anymore (for PS) */
285
    sl->with_wild= 0;
286
287
    if (saved_error || (saved_error= thd_arg->is_fatal_error))
288
      goto err;
289
    /*
290
      Use items list of underlaid select for derived tables to preserve
291
      information about fields lengths and exact types
292
    */
293
    if (!is_union_select)
294
      types= first_sl->item_list;
295
    else if (sl == first_sl)
296
    {
297
      /*
298
        We need to create an empty table object. It is used
299
        to create tmp_table fields in Item_type_holder.
300
        The main reason of this is that we can't create
301
        field object without table.
302
      */
303
      DBUG_ASSERT(!empty_table);
304
      empty_table= (TABLE*) thd->calloc(sizeof(TABLE));
305
      types.empty();
306
      List_iterator_fast<Item> it(sl->item_list);
307
      Item *item_tmp;
308
      while ((item_tmp= it++))
309
      {
310
	/* Error's in 'new' will be detected after loop */
311
	types.push_back(new Item_type_holder(thd_arg, item_tmp));
312
      }
313
314
      if (thd_arg->is_fatal_error)
315
	goto err; // out of memory
316
    }
317
    else
318
    {
319
      if (types.elements != sl->item_list.elements)
320
      {
321
	my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
322
		   ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
323
	goto err;
324
      }
325
      List_iterator_fast<Item> it(sl->item_list);
326
      List_iterator_fast<Item> tp(types);	
327
      Item *type, *item_tmp;
328
      while ((type= tp++, item_tmp= it++))
329
      {
330
        if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
331
	  DBUG_RETURN(TRUE);
332
      }
333
    }
334
  }
335
336
  if (is_union_select)
337
  {
338
    /*
339
      Check that it was possible to aggregate
340
      all collations together for UNION.
341
    */
342
    List_iterator_fast<Item> tp(types);
343
    Item *type;
344
    ulonglong create_options;
345
346
    while ((type= tp++))
347
    {
348
      if (type->result_type() == STRING_RESULT &&
349
          type->collation.derivation == DERIVATION_NONE)
350
      {
351
        my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), "UNION");
352
        goto err;
353
      }
354
    }
355
    
356
    create_options= (first_sl->options | thd_arg->options |
357
                     TMP_TABLE_ALL_COLUMNS);
358
359
    if (union_result->create_result_table(thd, &types, test(union_distinct),
360
                                          create_options, "", FALSE))
361
      goto err;
362
    bzero((char*) &result_table_list, sizeof(result_table_list));
363
    result_table_list.db= (char*) "";
364
    result_table_list.table_name= result_table_list.alias= (char*) "union";
365
    result_table_list.table= table= union_result->table;
366
367
    thd_arg->lex->current_select= lex_select_save;
368
    if (!item_list.elements)
369
    {
370
      saved_error= table->fill_item_list(&item_list);
371
      if (saved_error)
372
        goto err;
373
    }
374
    else
375
    {
376
      DBUG_ASSERT(thd->stmt_arena->is_conventional() == false);
377
      /*
378
        We're in execution of a prepared statement or stored procedure:
379
        reset field items to point at fields from the created temporary table.
380
      */
381
      table->reset_item_list(&item_list);
382
    }
383
  }
384
385
  thd_arg->lex->current_select= lex_select_save;
386
387
  DBUG_RETURN(saved_error || thd_arg->is_fatal_error);
388
389
err:
390
  thd_arg->lex->current_select= lex_select_save;
391
  DBUG_RETURN(TRUE);
392
}
393
394
395
bool st_select_lex_unit::exec()
396
{
397
  SELECT_LEX *lex_select_save= thd->lex->current_select;
398
  SELECT_LEX *select_cursor=first_select();
399
  ulonglong add_rows=0;
400
  ha_rows examined_rows= 0;
401
  DBUG_ENTER("st_select_lex_unit::exec");
402
403
  if (executed && !uncacheable && !describe)
404
    DBUG_RETURN(FALSE);
405
  executed= 1;
406
  
407
  if (uncacheable || !item || !item->assigned() || describe)
408
  {
409
    if (item)
410
      item->reset_value_registration();
411
    if (optimized && item)
412
    {
413
      if (item->assigned())
414
      {
415
        item->assigned(0); // We will reinit & rexecute unit
416
        item->reset();
417
        table->file->ha_delete_all_rows();
418
      }
419
      /* re-enabling indexes for next subselect iteration */
420
      if (union_distinct && table->file->ha_enable_indexes(HA_KEY_SWITCH_ALL))
421
      {
422
        DBUG_ASSERT(0);
423
      }
424
    }
425
    for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
426
    {
427
      ha_rows records_at_start= 0;
428
      thd->lex->current_select= sl;
429
430
      if (optimized)
431
	saved_error= sl->join->reinit();
432
      else
433
      {
434
        set_limit(sl);
435
	if (sl == global_parameters || describe)
436
	{
437
	  offset_limit_cnt= 0;
438
	  /*
439
	    We can't use LIMIT at this stage if we are using ORDER BY for the
440
	    whole query
441
	  */
442
	  if (sl->order_list.first || describe)
443
	    select_limit_cnt= HA_POS_ERROR;
444
        }
445
446
        /*
447
          When using braces, SQL_CALC_FOUND_ROWS affects the whole query:
448
          we don't calculate found_rows() per union part.
449
          Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
450
        */
451
        sl->join->select_options= 
452
          (select_limit_cnt == HA_POS_ERROR || sl->braces) ?
453
          sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
454
455
        /* dump_TABLE_LIST_struct(select_lex, select_lex->leaf_tables); */
456
        if (sl->join->flatten_subqueries())
457
          DBUG_RETURN(TRUE);
458
459
        /* dump_TABLE_LIST_struct(select_lex, select_lex->leaf_tables); */
460
	saved_error= sl->join->optimize();
461
      }
462
      if (!saved_error)
463
      {
464
	records_at_start= table->file->stats.records;
465
	sl->join->exec();
466
        if (sl == union_distinct)
467
	{
468
	  if (table->file->ha_disable_indexes(HA_KEY_SWITCH_ALL))
469
	    DBUG_RETURN(TRUE);
470
	  table->no_keyread=1;
471
	}
472
	saved_error= sl->join->error;
473
	offset_limit_cnt= (ha_rows)(sl->offset_limit ?
474
                                    sl->offset_limit->val_uint() :
475
                                    0);
476
	if (!saved_error)
477
	{
478
	  examined_rows+= thd->examined_row_count;
479
	  if (union_result->flush())
480
	  {
481
	    thd->lex->current_select= lex_select_save;
482
	    DBUG_RETURN(1);
483
	  }
484
	}
485
      }
486
      if (saved_error)
487
      {
488
	thd->lex->current_select= lex_select_save;
489
	DBUG_RETURN(saved_error);
490
      }
491
      /* Needed for the following test and for records_at_start in next loop */
492
      int error= table->file->info(HA_STATUS_VARIABLE);
493
      if(error)
494
      {
495
        table->file->print_error(error, MYF(0));
496
        DBUG_RETURN(1);
497
      }
498
      if (found_rows_for_union && !sl->braces && 
499
          select_limit_cnt != HA_POS_ERROR)
500
      {
501
	/*
502
	  This is a union without braces. Remember the number of rows that
503
	  could also have been part of the result set.
504
	  We get this from the difference of between total number of possible
505
	  rows and actual rows added to the temporary table.
506
	*/
507
	add_rows+= (ulonglong) (thd->limit_found_rows - (ulonglong)
508
			      ((table->file->stats.records -  records_at_start)));
509
      }
510
    }
511
  }
512
  optimized= 1;
513
514
  /* Send result to 'result' */
515
  saved_error= TRUE;
516
  {
517
    if (!thd->is_fatal_error)				// Check if EOM
518
    {
519
      set_limit(global_parameters);
520
      init_prepare_fake_select_lex(thd);
521
      JOIN *join= fake_select_lex->join;
522
      if (!join)
523
      {
524
	/*
525
	  allocate JOIN for fake select only once (prevent
526
	  mysql_select automatic allocation)
527
          TODO: The above is nonsense. mysql_select() will not allocate the
528
          join if one already exists. There must be some other reason why we
529
          don't let it allocate the join. Perhaps this is because we need
530
          some special parameter values passed to join constructor?
531
	*/
532
	if (!(fake_select_lex->join= new JOIN(thd, item_list,
533
					      fake_select_lex->options, result)))
534
	{
535
	  fake_select_lex->table_list.empty();
536
	  DBUG_RETURN(TRUE);
537
	}
538
        fake_select_lex->join->no_const_tables= TRUE;
539
540
	/*
541
	  Fake st_select_lex should have item list for correctref_array
542
	  allocation.
543
	*/
544
	fake_select_lex->item_list= item_list;
545
        saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
546
                              &result_table_list,
547
                              0, item_list, NULL,
548
                              global_parameters->order_list.elements,
549
                              (ORDER*)global_parameters->order_list.first,
550
                              (ORDER*) NULL, NULL, (ORDER*) NULL,
551
                              fake_select_lex->options | SELECT_NO_UNLOCK,
552
                              result, this, fake_select_lex);
553
      }
554
      else
555
      {
556
        if (describe)
557
        {
558
          /*
559
            In EXPLAIN command, constant subqueries that do not use any
560
            tables are executed two times:
561
             - 1st time is a real evaluation to get the subquery value
562
             - 2nd time is to produce EXPLAIN output rows.
563
            1st execution sets certain members (e.g. select_result) to perform
564
            subquery execution rather than EXPLAIN line production. In order 
565
            to reset them back, we re-do all of the actions (yes it is ugly):
566
          */
567
	  join->init(thd, item_list, fake_select_lex->options, result);
568
          saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
569
                                &result_table_list,
570
                                0, item_list, NULL,
571
                                global_parameters->order_list.elements,
572
                                (ORDER*)global_parameters->order_list.first,
573
                                (ORDER*) NULL, NULL, (ORDER*) NULL,
574
                                fake_select_lex->options | SELECT_NO_UNLOCK,
575
                                result, this, fake_select_lex);
576
        }
577
        else
578
        {
579
          join->examined_rows= 0;
580
          saved_error= join->reinit();
581
          join->exec();
582
        }
583
      }
584
585
      fake_select_lex->table_list.empty();
586
      if (!saved_error)
587
      {
588
	thd->limit_found_rows = (ulonglong)table->file->stats.records + add_rows;
589
        thd->examined_row_count+= examined_rows;
590
      }
591
      /*
592
	Mark for slow query log if any of the union parts didn't use
593
	indexes efficiently
594
      */
595
    }
596
  }
597
  thd->lex->current_select= lex_select_save;
598
  DBUG_RETURN(saved_error);
599
}
600
601
602
bool st_select_lex_unit::cleanup()
603
{
604
  int error= 0;
605
  DBUG_ENTER("st_select_lex_unit::cleanup");
606
607
  if (cleaned)
608
  {
609
    DBUG_RETURN(FALSE);
610
  }
611
  cleaned= 1;
612
613
  if (union_result)
614
  {
615
    delete union_result;
616
    union_result=0; // Safety
617
    if (table)
618
      free_tmp_table(thd, table);
619
    table= 0; // Safety
620
  }
621
622
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
623
    error|= sl->cleanup();
624
625
  if (fake_select_lex)
626
  {
627
    JOIN *join;
628
    if ((join= fake_select_lex->join))
629
    {
630
      join->tables_list= 0;
631
      join->tables= 0;
632
    }
633
    error|= fake_select_lex->cleanup();
634
    if (fake_select_lex->order_list.elements)
635
    {
636
      ORDER *ord;
637
      for (ord= (ORDER*)fake_select_lex->order_list.first; ord; ord= ord->next)
638
        (*ord->item)->cleanup();
639
    }
640
  }
641
642
  DBUG_RETURN(error);
643
}
644
645
646
void st_select_lex_unit::reinit_exec_mechanism()
647
{
648
  prepared= optimized= executed= 0;
649
#ifndef DBUG_OFF
650
  if (is_union())
651
  {
652
    List_iterator_fast<Item> it(item_list);
653
    Item *field;
654
    while ((field= it++))
655
    {
656
      /*
657
	we can't cleanup here, because it broke link to temporary table field,
658
	but have to drop fixed flag to allow next fix_field of this field
659
	during re-executing
660
      */
661
      field->fixed= 0;
662
    }
663
  }
664
#endif
665
}
666
667
668
/*
669
  change select_result object of unit
670
671
  SYNOPSIS
672
    st_select_lex_unit::change_result()
673
    result	new select_result object
674
    old_result	old select_result object
675
676
  RETURN
677
    FALSE - OK
678
    TRUE  - error
679
*/
680
681
bool st_select_lex_unit::change_result(select_result_interceptor *new_result,
682
                                       select_result_interceptor *old_result)
683
{
684
  bool res= FALSE;
685
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
686
  {
687
    if (sl->join && sl->join->result == old_result)
688
      if (sl->join->change_result(new_result))
689
	return TRUE;
690
  }
691
  if (fake_select_lex && fake_select_lex->join)
692
    res= fake_select_lex->join->change_result(new_result);
693
  return (res);
694
}
695
696
/*
697
  Get column type information for this unit.
698
699
  SYNOPSIS
700
    st_select_lex_unit::get_unit_column_types()
701
702
  DESCRIPTION
703
    For a single-select the column types are taken
704
    from the list of selected items. For a union this function
705
    assumes that st_select_lex_unit::prepare has been called
706
    and returns the type holders that were created for unioned
707
    column types of all selects.
708
709
  NOTES
710
    The implementation of this function should be in sync with
711
    st_select_lex_unit::prepare()
712
*/
713
714
List<Item> *st_select_lex_unit::get_unit_column_types()
715
{
716
  SELECT_LEX *sl= first_select();
717
718
  if (is_union())
719
  {
720
    DBUG_ASSERT(prepared);
721
    /* Types are generated during prepare */
722
    return &types;
723
  }
724
725
  return &sl->item_list;
726
}
727
728
bool st_select_lex::cleanup()
729
{
730
  bool error= FALSE;
731
  DBUG_ENTER("st_select_lex::cleanup()");
732
733
  if (join)
734
  {
735
    DBUG_ASSERT((st_select_lex*)join->select_lex == this);
736
    error= join->destroy();
737
    delete join;
738
    join= 0;
739
  }
740
  for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ;
741
       lex_unit= lex_unit->next_unit())
742
  {
743
    error= (bool) ((uint) error | (uint) lex_unit->cleanup());
744
  }
745
  non_agg_fields.empty();
746
  inner_refs_list.empty();
747
  DBUG_RETURN(error);
748
}
749
750
751
void st_select_lex::cleanup_all_joins(bool full)
752
{
753
  SELECT_LEX_UNIT *unit;
754
  SELECT_LEX *sl;
755
756
  if (join)
757
    join->cleanup(full);
758
759
  for (unit= first_inner_unit(); unit; unit= unit->next_unit())
760
    for (sl= unit->first_select(); sl; sl= sl->next_select())
761
      sl->cleanup_all_joins(full);
762
}