~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_union.cc

  • Committer: Brian Aker
  • Date: 2008-12-15 19:32:58 UTC
  • mfrom: (677.1.2 devel)
  • Revision ID: brian@tangent.org-20081215193258-fsvc1sh9h7a9sb1t
Merge from Monty

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/*
17
17
  UNION  of select's
18
18
  UNION's  were introduced by Monty and Sinisa <sinisa@mysql.com>
19
19
*/
20
 
#include "config.h"
 
20
#include <drizzled/server_includes.h>
21
21
#include <drizzled/sql_select.h>
22
22
#include <drizzled/error.h>
23
23
#include <drizzled/item/type_holder.h>
24
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)
 
25
 
 
26
bool mysql_union(Session *session, LEX *, select_result *result,
 
27
                 SELECT_LEX_UNIT *unit, ulong setup_tables_done_option)
32
28
{
33
29
  bool res;
34
30
  if (!(res= unit->prepare(session, result, SELECT_NO_UNLOCK |
44
40
** store records in temporary table for UNION
45
41
***************************************************************************/
46
42
 
47
 
int select_union::prepare(List<Item> &, Select_Lex_Unit *u)
 
43
int select_union::prepare(List<Item> &, SELECT_LEX_UNIT *u)
48
44
{
49
45
  unit= u;
50
46
  return 0;
59
55
    unit->offset_limit_cnt--;
60
56
    return 0;
61
57
  }
62
 
  fill_record(session, table->getFields(), values, true);
 
58
  fill_record(session, table->field, values, 1);
63
59
  if (session->is_error())
64
60
    return 1;
65
61
 
66
 
  if ((error= table->cursor->insertRecord(table->getInsertRecord())))
 
62
  if ((error= table->file->ha_write_row(table->record[0])))
67
63
  {
68
64
    /* create_myisam_from_heap will generate error if needed */
69
 
    if (table->cursor->is_fatal_error(error, HA_CHECK_DUP))
70
 
    {
71
 
      my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
72
 
      return true;
73
 
    }
 
65
    if (table->file->is_fatal_error(error, HA_CHECK_DUP) &&
 
66
        create_myisam_from_heap(session, table, tmp_table_param.start_recinfo,
 
67
                                &tmp_table_param.recinfo, error, 1))
 
68
      return 1;
74
69
  }
75
70
  return 0;
76
71
}
85
80
bool select_union::flush()
86
81
{
87
82
  int error;
88
 
  if ((error=table->cursor->extra(HA_EXTRA_NO_CACHE)))
 
83
  if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
89
84
  {
90
 
    table->print_error(error, MYF(0));
 
85
    table->file->print_error(error, MYF(0));
91
86
    return 1;
92
87
  }
93
88
  return 0;
105
100
                         duplicates on insert
106
101
      options            create options
107
102
      table_alias        name of the temporary table
 
103
      bit_fields_as_long convert bit fields to uint64_t
108
104
 
109
105
  DESCRIPTION
110
106
    Create a temporary table that is used to store the result of a UNION,
118
114
bool
119
115
select_union::create_result_table(Session *session_arg, List<Item> *column_types,
120
116
                                  bool is_union_distinct, uint64_t options,
121
 
                                  const char *table_alias)
 
117
                                  const char *table_alias,
 
118
                                  bool bit_fields_as_long)
122
119
{
123
 
  assert(table == NULL);
 
120
  assert(table == 0);
124
121
  tmp_table_param.init();
125
122
  tmp_table_param.field_count= column_types->elements;
 
123
  tmp_table_param.bit_fields_as_long= bit_fields_as_long;
126
124
 
127
125
  if (! (table= create_tmp_table(session_arg, &tmp_table_param, *column_types,
128
 
                                 (Order*) NULL, is_union_distinct, 1,
 
126
                                 (order_st*) 0, is_union_distinct, 1,
129
127
                                 options, HA_POS_ERROR, (char*) table_alias)))
130
 
  {
131
128
    return true;
132
 
  }
133
 
 
134
 
  table->cursor->extra(HA_EXTRA_WRITE_CACHE);
135
 
  table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
136
 
 
 
129
  table->file->extra(HA_EXTRA_WRITE_CACHE);
 
130
  table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
137
131
  return false;
138
132
}
139
133
 
147
141
 
148
142
void select_union::cleanup()
149
143
{
150
 
  table->cursor->extra(HA_EXTRA_RESET_STATE);
151
 
  table->cursor->ha_delete_all_rows();
152
 
  table->free_io_cache();
153
 
  table->filesort_free_buffers();
 
144
  table->file->extra(HA_EXTRA_RESET_STATE);
 
145
  table->file->ha_delete_all_rows();
 
146
  free_io_cache(table);
 
147
  filesort_free_buffers(table,0);
154
148
}
155
149
 
156
150
 
158
152
  initialization procedures before fake_select_lex preparation()
159
153
 
160
154
  SYNOPSIS
161
 
    Select_Lex_Unit::init_prepare_fake_select_lex()
 
155
    st_select_lex_unit::init_prepare_fake_select_lex()
162
156
    session             - thread handler
163
157
 
164
158
  RETURN
166
160
*/
167
161
 
168
162
void
169
 
Select_Lex_Unit::init_prepare_fake_select_lex(Session *session_arg)
 
163
st_select_lex_unit::init_prepare_fake_select_lex(Session *session_arg)
170
164
{
171
165
  session_arg->lex->current_select= fake_select_lex;
172
166
  fake_select_lex->table_list.link_in_list((unsigned char *)&result_table_list,
176
170
    fake_select_lex->context.first_name_resolution_table=
177
171
    fake_select_lex->get_table_list();
178
172
 
179
 
  for (Order *order= (Order *) global_parameters->order_list.first;
 
173
  for (order_st *order= (order_st *) global_parameters->order_list.first;
180
174
       order;
181
175
       order= order->next)
182
176
    order->item= &order->item_ptr;
183
177
 
184
 
  for (Order *order= (Order *)global_parameters->order_list.first;
 
178
  for (order_st *order= (order_st *)global_parameters->order_list.first;
185
179
       order;
186
180
       order=order->next)
187
181
  {
191
185
}
192
186
 
193
187
 
194
 
bool Select_Lex_Unit::prepare(Session *session_arg, select_result *sel_result,
195
 
                              uint64_t additional_options)
 
188
bool st_select_lex_unit::prepare(Session *session_arg, select_result *sel_result,
 
189
                                 uint32_t additional_options)
196
190
{
197
 
  Select_Lex *lex_select_save= session_arg->lex->current_select;
198
 
  Select_Lex *sl, *first_sl= first_select();
 
191
  SELECT_LEX *lex_select_save= session_arg->lex->current_select;
 
192
  SELECT_LEX *sl, *first_sl= first_select();
199
193
  select_result *tmp_result;
200
194
  bool is_union_select;
201
195
  Table *empty_table= 0;
253
247
  {
254
248
    bool can_skip_order_by;
255
249
    sl->options|=  SELECT_NO_UNLOCK;
256
 
    Join *join= new Join(session_arg, sl->item_list,
 
250
    JOIN *join= new JOIN(session_arg, sl->item_list,
257
251
                         sl->options | session_arg->options | additional_options,
258
252
                         tmp_result);
259
253
    /*
278
272
                                sl->order_list.elements) +
279
273
                               sl->group_list.elements,
280
274
                               can_skip_order_by ?
281
 
                               (Order*) NULL : (Order *)sl->order_list.first,
282
 
                               (Order*) sl->group_list.first,
 
275
                               (order_st*) 0 : (order_st *)sl->order_list.first,
 
276
                               (order_st*) sl->group_list.first,
283
277
                               sl->having,
 
278
                               (is_union_select ? (order_st*) 0 :
 
279
                                (order_st*) session_arg->lex->proc_list.first),
284
280
                               sl, this);
285
281
    /* There are no * in the statement anymore (for PS) */
286
282
    sl->with_wild= 0;
358
354
                     TMP_TABLE_ALL_COLUMNS);
359
355
 
360
356
    if (union_result->create_result_table(session, &types, test(union_distinct),
361
 
                                          create_options, ""))
 
357
                                          create_options, "", false))
362
358
      goto err;
363
359
    memset(&result_table_list, 0, sizeof(result_table_list));
364
 
    result_table_list.setSchemaName((char*) "");
365
 
    result_table_list.alias= "union";
366
 
    result_table_list.setTableName((char *) "union");
 
360
    result_table_list.db= (char*) "";
 
361
    result_table_list.table_name= result_table_list.alias= (char*) "union";
367
362
    result_table_list.table= table= union_result->table;
368
363
 
369
364
    session_arg->lex->current_select= lex_select_save;
393
388
}
394
389
 
395
390
 
396
 
bool Select_Lex_Unit::exec()
 
391
bool st_select_lex_unit::exec()
397
392
{
398
 
  Select_Lex *lex_select_save= session->lex->current_select;
399
 
  Select_Lex *select_cursor=first_select();
 
393
  SELECT_LEX *lex_select_save= session->lex->current_select;
 
394
  SELECT_LEX *select_cursor=first_select();
400
395
  uint64_t add_rows=0;
401
396
  ha_rows examined_rows= 0;
402
397
 
403
 
  if (executed && uncacheable.none() && ! describe)
404
 
    return false;
 
398
  if (executed && !uncacheable && !describe)
 
399
    return(false);
405
400
  executed= 1;
406
401
 
407
 
  if (uncacheable.any() || ! item || ! item->assigned() || describe)
 
402
  if (uncacheable || !item || !item->assigned() || describe)
408
403
  {
409
404
    if (item)
410
405
      item->reset_value_registration();
414
409
      {
415
410
        item->assigned(0); // We will reinit & rexecute unit
416
411
        item->reset();
417
 
        table->cursor->ha_delete_all_rows();
 
412
        table->file->ha_delete_all_rows();
418
413
      }
419
414
      /* re-enabling indexes for next subselect iteration */
420
 
      if (union_distinct && table->cursor->ha_enable_indexes(HA_KEY_SWITCH_ALL))
 
415
      if (union_distinct && table->file->ha_enable_indexes(HA_KEY_SWITCH_ALL))
421
416
      {
422
417
        assert(0);
423
418
      }
424
419
    }
425
 
    for (Select_Lex *sl= select_cursor; sl; sl= sl->next_select())
 
420
    for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
426
421
    {
427
422
      ha_rows records_at_start= 0;
428
423
      session->lex->current_select= sl;
436
431
        {
437
432
          offset_limit_cnt= 0;
438
433
          /*
439
 
            We can't use LIMIT at this stage if we are using ORDER BY for the
 
434
            We can't use LIMIT at this stage if we are using order_st BY for the
440
435
            whole query
441
436
          */
442
437
          if (sl->order_list.first || describe)
452
447
          (select_limit_cnt == HA_POS_ERROR || sl->braces) ?
453
448
          sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
454
449
 
 
450
        if (sl->join->flatten_subqueries())
 
451
          return(true);
 
452
 
455
453
        saved_error= sl->join->optimize();
456
454
      }
457
455
      if (!saved_error)
458
456
      {
459
 
        records_at_start= table->cursor->stats.records;
 
457
        records_at_start= table->file->stats.records;
460
458
        sl->join->exec();
461
459
        if (sl == union_distinct)
462
460
        {
463
 
          if (table->cursor->ha_disable_indexes(HA_KEY_SWITCH_ALL))
 
461
          if (table->file->ha_disable_indexes(HA_KEY_SWITCH_ALL))
464
462
            return(true);
465
463
          table->no_keyread=1;
466
464
        }
484
482
        return(saved_error);
485
483
      }
486
484
      /* Needed for the following test and for records_at_start in next loop */
487
 
      int error= table->cursor->info(HA_STATUS_VARIABLE);
488
 
      if (error)
 
485
      int error= table->file->info(HA_STATUS_VARIABLE);
 
486
      if(error)
489
487
      {
490
 
        table->print_error(error, MYF(0));
 
488
        table->file->print_error(error, MYF(0));
491
489
        return(1);
492
490
      }
493
491
      if (found_rows_for_union && !sl->braces &&
500
498
          rows and actual rows added to the temporary table.
501
499
        */
502
500
        add_rows+= (uint64_t) (session->limit_found_rows - (uint64_t)
503
 
                              ((table->cursor->stats.records -  records_at_start)));
 
501
                              ((table->file->stats.records -  records_at_start)));
504
502
      }
505
503
    }
506
504
  }
513
511
    {
514
512
      set_limit(global_parameters);
515
513
      init_prepare_fake_select_lex(session);
516
 
      Join *join= fake_select_lex->join;
 
514
      JOIN *join= fake_select_lex->join;
517
515
      if (!join)
518
516
      {
519
517
        /*
520
518
          allocate JOIN for fake select only once (prevent
521
 
          select_query automatic allocation)
522
 
          TODO: The above is nonsense. select_query() will not allocate the
 
519
          mysql_select automatic allocation)
 
520
          TODO: The above is nonsense. mysql_select() will not allocate the
523
521
          join if one already exists. There must be some other reason why we
524
522
          don't let it allocate the join. Perhaps this is because we need
525
523
          some special parameter values passed to join constructor?
526
524
        */
527
 
        if (!(fake_select_lex->join= new Join(session, item_list,
 
525
        if (!(fake_select_lex->join= new JOIN(session, item_list,
528
526
                                              fake_select_lex->options, result)))
529
527
        {
530
528
          fake_select_lex->table_list.empty();
533
531
        fake_select_lex->join->no_const_tables= true;
534
532
 
535
533
        /*
536
 
          Fake Select_Lex should have item list for correctref_array
 
534
          Fake st_select_lex should have item list for correctref_array
537
535
          allocation.
538
536
        */
539
537
        fake_select_lex->item_list= item_list;
540
 
        saved_error= select_query(session, &fake_select_lex->ref_pointer_array,
 
538
        saved_error= mysql_select(session, &fake_select_lex->ref_pointer_array,
541
539
                              &result_table_list,
542
540
                              0, item_list, NULL,
543
541
                              global_parameters->order_list.elements,
544
 
                              (Order*)global_parameters->order_list.first,
545
 
                              (Order*) NULL, NULL,
 
542
                              (order_st*)global_parameters->order_list.first,
 
543
                              (order_st*) NULL, NULL, (order_st*) NULL,
546
544
                              fake_select_lex->options | SELECT_NO_UNLOCK,
547
545
                              result, this, fake_select_lex);
548
546
      }
559
557
            subquery execution rather than EXPLAIN line production. In order
560
558
            to reset them back, we re-do all of the actions (yes it is ugly):
561
559
          */
562
 
                join->reset(session, item_list, fake_select_lex->options, result);
563
 
          saved_error= select_query(session, &fake_select_lex->ref_pointer_array,
 
560
          join->init(session, item_list, fake_select_lex->options, result);
 
561
          saved_error= mysql_select(session, &fake_select_lex->ref_pointer_array,
564
562
                                &result_table_list,
565
563
                                0, item_list, NULL,
566
564
                                global_parameters->order_list.elements,
567
 
                                (Order*)global_parameters->order_list.first,
568
 
                                (Order*) NULL, NULL,
 
565
                                (order_st*)global_parameters->order_list.first,
 
566
                                (order_st*) NULL, NULL, (order_st*) NULL,
569
567
                                fake_select_lex->options | SELECT_NO_UNLOCK,
570
568
                                result, this, fake_select_lex);
571
569
        }
580
578
      fake_select_lex->table_list.empty();
581
579
      if (!saved_error)
582
580
      {
583
 
        session->limit_found_rows = (uint64_t)table->cursor->stats.records + add_rows;
 
581
        session->limit_found_rows = (uint64_t)table->file->stats.records + add_rows;
584
582
        session->examined_row_count+= examined_rows;
585
583
      }
586
584
      /*
594
592
}
595
593
 
596
594
 
597
 
bool Select_Lex_Unit::cleanup()
 
595
bool st_select_lex_unit::cleanup()
598
596
{
599
597
  int error= 0;
600
598
 
608
606
  {
609
607
    delete union_result;
610
608
    union_result=0; // Safety
 
609
    if (table)
 
610
      table->free_tmp_table(session);
611
611
    table= 0; // Safety
612
612
  }
613
613
 
614
 
  for (Select_Lex *sl= first_select(); sl; sl= sl->next_select())
 
614
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
615
615
    error|= sl->cleanup();
616
616
 
617
617
  if (fake_select_lex)
618
618
  {
619
 
    Join *join;
 
619
    JOIN *join;
620
620
    if ((join= fake_select_lex->join))
621
621
    {
622
622
      join->tables_list= 0;
625
625
    error|= fake_select_lex->cleanup();
626
626
    if (fake_select_lex->order_list.elements)
627
627
    {
628
 
      Order *ord;
629
 
      for (ord= (Order*)fake_select_lex->order_list.first; ord; ord= ord->next)
 
628
      order_st *ord;
 
629
      for (ord= (order_st*)fake_select_lex->order_list.first; ord; ord= ord->next)
630
630
        (*ord->item)->cleanup();
631
631
    }
632
632
  }
635
635
}
636
636
 
637
637
 
638
 
void Select_Lex_Unit::reinit_exec_mechanism()
 
638
void st_select_lex_unit::reinit_exec_mechanism()
639
639
{
640
640
  prepared= optimized= executed= 0;
641
641
}
645
645
  change select_result object of unit
646
646
 
647
647
  SYNOPSIS
648
 
    Select_Lex_Unit::change_result()
 
648
    st_select_lex_unit::change_result()
649
649
    result      new select_result object
650
650
    old_result  old select_result object
651
651
 
654
654
    true  - error
655
655
*/
656
656
 
657
 
bool Select_Lex_Unit::change_result(select_result_interceptor *new_result,
 
657
bool st_select_lex_unit::change_result(select_result_interceptor *new_result,
658
658
                                       select_result_interceptor *old_result)
659
659
{
660
660
  bool res= false;
661
 
  for (Select_Lex *sl= first_select(); sl; sl= sl->next_select())
 
661
  for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
662
662
  {
663
663
    if (sl->join && sl->join->result == old_result)
664
664
      if (sl->join->change_result(new_result))
673
673
  Get column type information for this unit.
674
674
 
675
675
  SYNOPSIS
676
 
    Select_Lex_Unit::get_unit_column_types()
 
676
    st_select_lex_unit::get_unit_column_types()
677
677
 
678
678
  DESCRIPTION
679
679
    For a single-select the column types are taken
680
680
    from the list of selected items. For a union this function
681
 
    assumes that Select_Lex_Unit::prepare has been called
 
681
    assumes that st_select_lex_unit::prepare has been called
682
682
    and returns the type holders that were created for unioned
683
683
    column types of all selects.
684
684
 
685
685
  NOTES
686
686
    The implementation of this function should be in sync with
687
 
    Select_Lex_Unit::prepare()
 
687
    st_select_lex_unit::prepare()
688
688
*/
689
689
 
690
 
List<Item> *Select_Lex_Unit::get_unit_column_types()
 
690
List<Item> *st_select_lex_unit::get_unit_column_types()
691
691
{
692
 
  Select_Lex *sl= first_select();
 
692
  SELECT_LEX *sl= first_select();
693
693
 
694
694
  if (is_union())
695
695
  {
701
701
  return &sl->item_list;
702
702
}
703
703
 
704
 
bool Select_Lex::cleanup()
 
704
bool st_select_lex::cleanup()
705
705
{
706
706
  bool error= false;
707
707
 
708
708
  if (join)
709
709
  {
710
 
    assert((Select_Lex*)join->select_lex == this);
 
710
    assert((st_select_lex*)join->select_lex == this);
711
711
    error= join->destroy();
712
712
    delete join;
713
713
    join= 0;
714
714
  }
715
 
  for (Select_Lex_Unit *lex_unit= first_inner_unit(); lex_unit ;
 
715
  for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ;
716
716
       lex_unit= lex_unit->next_unit())
717
717
  {
718
 
    error= (bool) ((uint32_t) error | (uint32_t) lex_unit->cleanup());
 
718
    error= (bool) ((uint) error | (uint) lex_unit->cleanup());
719
719
  }
720
720
  non_agg_fields.empty();
721
721
  inner_refs_list.empty();
723
723
}
724
724
 
725
725
 
726
 
void Select_Lex::cleanup_all_joins(bool full)
 
726
void st_select_lex::cleanup_all_joins(bool full)
727
727
{
728
 
  Select_Lex_Unit *unit;
729
 
  Select_Lex *sl;
 
728
  SELECT_LEX_UNIT *unit;
 
729
  SELECT_LEX *sl;
730
730
 
731
731
  if (join)
732
732
    join->cleanup(full);
735
735
    for (sl= unit->first_select(); sl; sl= sl->next_select())
736
736
      sl->cleanup_all_joins(full);
737
737
}
738
 
 
739
 
} /* namespace drizzled */