~ubuntu-branches/ubuntu/saucy/drizzle/saucy-proposed

« back to all changes in this revision

Viewing changes to drizzled/sql_union.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

Show diffs side-by-side

added added

removed removed

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