~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_union.cc

  • Committer: Monty Taylor
  • Date: 2009-03-18 18:45:23 UTC
  • mto: (950.1.1 mordred)
  • mto: This revision was merged to the branch mainline in revision 943.
  • Revision ID: mordred@inaugust.com-20090318184523-mfbjyj5wkipv4n3b
Moved big tests to big suite. Added make target "make test-big" to allow for easy running of the big tests.

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>
21
 
 
 
20
#include <drizzled/server_includes.h>
22
21
#include <drizzled/sql_select.h>
23
22
#include <drizzled/error.h>
24
23
#include <drizzled/item/type_holder.h>
25
24
#include <drizzled/sql_base.h>
26
 
#include <drizzled/sql_union.h>
27
 
#include <drizzled/select_union.h>
28
 
#include <drizzled/sql_lex.h>
29
 
#include <drizzled/session.h>
30
 
 
31
 
namespace drizzled
32
 
{
33
 
 
34
 
bool drizzle_union(Session *session, LEX *, select_result *result,
35
 
                   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, uint64_t setup_tables_done_option)
36
28
{
37
29
  bool res;
38
30
  if (!(res= unit->prepare(session, result, SELECT_NO_UNLOCK |
63
55
    unit->offset_limit_cnt--;
64
56
    return 0;
65
57
  }
66
 
  fill_record(session, table->getFields(), values, true);
 
58
  fill_record(session, table->field, values, 1);
67
59
  if (session->is_error())
68
60
    return 1;
69
61
 
70
 
  if ((error= table->cursor->insertRecord(table->getInsertRecord())))
 
62
  if ((error= table->file->ha_write_row(table->record[0])))
71
63
  {
72
64
    /* create_myisam_from_heap will generate error if needed */
73
 
    if (table->cursor->is_fatal_error(error, HA_CHECK_DUP))
74
 
    {
75
 
      my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
76
 
      return true;
77
 
    }
 
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;
78
69
  }
79
70
  return 0;
80
71
}
89
80
bool select_union::flush()
90
81
{
91
82
  int error;
92
 
  if ((error=table->cursor->extra(HA_EXTRA_NO_CACHE)))
 
83
  if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
93
84
  {
94
 
    table->print_error(error, MYF(0));
 
85
    table->file->print_error(error, MYF(0));
95
86
    return 1;
96
87
  }
97
88
  return 0;
109
100
                         duplicates on insert
110
101
      options            create options
111
102
      table_alias        name of the temporary table
 
103
      bit_fields_as_long convert bit fields to uint64_t
112
104
 
113
105
  DESCRIPTION
114
106
    Create a temporary table that is used to store the result of a UNION,
122
114
bool
123
115
select_union::create_result_table(Session *session_arg, List<Item> *column_types,
124
116
                                  bool is_union_distinct, uint64_t options,
125
 
                                  const char *table_alias)
 
117
                                  const char *table_alias,
 
118
                                  bool bit_fields_as_long)
126
119
{
127
 
  assert(table == NULL);
 
120
  assert(table == 0);
128
121
  tmp_table_param.init();
129
122
  tmp_table_param.field_count= column_types->elements;
 
123
  tmp_table_param.bit_fields_as_long= bit_fields_as_long;
130
124
 
131
125
  if (! (table= create_tmp_table(session_arg, &tmp_table_param, *column_types,
132
 
                                 (Order*) NULL, is_union_distinct, 1,
 
126
                                 (order_st*) 0, is_union_distinct, 1,
133
127
                                 options, HA_POS_ERROR, (char*) table_alias)))
134
 
  {
135
128
    return true;
136
 
  }
137
 
 
138
 
  table->cursor->extra(HA_EXTRA_WRITE_CACHE);
139
 
  table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
140
 
 
 
129
  table->file->extra(HA_EXTRA_WRITE_CACHE);
 
130
  table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
141
131
  return false;
142
132
}
143
133
 
151
141
 
152
142
void select_union::cleanup()
153
143
{
154
 
  table->cursor->extra(HA_EXTRA_RESET_STATE);
155
 
  table->cursor->ha_delete_all_rows();
156
 
  table->free_io_cache();
157
 
  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);
158
148
}
159
149
 
160
150
 
172
162
void
173
163
Select_Lex_Unit::init_prepare_fake_select_lex(Session *session_arg)
174
164
{
175
 
  session_arg->getLex()->current_select= fake_select_lex;
 
165
  session_arg->lex->current_select= fake_select_lex;
176
166
  fake_select_lex->table_list.link_in_list((unsigned char *)&result_table_list,
177
167
                                           (unsigned char **)
178
168
                                           &result_table_list.next_local);
180
170
    fake_select_lex->context.first_name_resolution_table=
181
171
    fake_select_lex->get_table_list();
182
172
 
183
 
  for (Order *order= (Order *) global_parameters->order_list.first;
 
173
  for (order_st *order= (order_st *) global_parameters->order_list.first;
184
174
       order;
185
175
       order= order->next)
186
176
    order->item= &order->item_ptr;
187
177
 
188
 
  for (Order *order= (Order *)global_parameters->order_list.first;
 
178
  for (order_st *order= (order_st *)global_parameters->order_list.first;
189
179
       order;
190
180
       order=order->next)
191
181
  {
198
188
bool Select_Lex_Unit::prepare(Session *session_arg, select_result *sel_result,
199
189
                              uint64_t additional_options)
200
190
{
201
 
  Select_Lex *lex_select_save= session_arg->getLex()->current_select;
 
191
  Select_Lex *lex_select_save= session_arg->lex->current_select;
202
192
  Select_Lex *sl, *first_sl= first_select();
203
193
  select_result *tmp_result;
204
194
  bool is_union_select;
235
225
  prepared= 1;
236
226
  saved_error= false;
237
227
 
238
 
  session_arg->getLex()->current_select= sl= first_sl;
 
228
  session_arg->lex->current_select= sl= first_sl;
239
229
  found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
240
230
  is_union_select= is_union() || fake_select_lex;
241
231
 
257
247
  {
258
248
    bool can_skip_order_by;
259
249
    sl->options|=  SELECT_NO_UNLOCK;
260
 
    Join *join= new Join(session_arg, sl->item_list,
 
250
    JOIN *join= new JOIN(session_arg, sl->item_list,
261
251
                         sl->options | session_arg->options | additional_options,
262
252
                         tmp_result);
263
253
    /*
270
260
    if (!join)
271
261
      goto err;
272
262
 
273
 
    session_arg->getLex()->current_select= sl;
 
263
    session_arg->lex->current_select= sl;
274
264
 
275
265
    can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit);
276
266
 
282
272
                                sl->order_list.elements) +
283
273
                               sl->group_list.elements,
284
274
                               can_skip_order_by ?
285
 
                               (Order*) NULL : (Order *)sl->order_list.first,
286
 
                               (Order*) sl->group_list.first,
 
275
                               (order_st*) 0 : (order_st *)sl->order_list.first,
 
276
                               (order_st*) sl->group_list.first,
287
277
                               sl->having,
288
278
                               sl, this);
289
279
    /* There are no * in the statement anymore (for PS) */
307
297
      */
308
298
      assert(!empty_table);
309
299
      empty_table= (Table*) session->calloc(sizeof(Table));
310
 
      types.clear();
311
 
      List<Item>::iterator it(sl->item_list.begin());
 
300
      types.empty();
 
301
      List_iterator_fast<Item> it(sl->item_list);
312
302
      Item *item_tmp;
313
303
      while ((item_tmp= it++))
314
304
      {
327
317
                   ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
328
318
        goto err;
329
319
      }
330
 
      List<Item>::iterator it(sl->item_list.begin());
331
 
      List<Item>::iterator tp(types.begin());
 
320
      List_iterator_fast<Item> it(sl->item_list);
 
321
      List_iterator_fast<Item> tp(types);
332
322
      Item *type, *item_tmp;
333
323
      while ((type= tp++, item_tmp= it++))
334
324
      {
344
334
      Check that it was possible to aggregate
345
335
      all collations together for UNION.
346
336
    */
347
 
    List<Item>::iterator tp(types.begin());
 
337
    List_iterator_fast<Item> tp(types);
348
338
    Item *type;
349
339
    uint64_t create_options;
350
340
 
362
352
                     TMP_TABLE_ALL_COLUMNS);
363
353
 
364
354
    if (union_result->create_result_table(session, &types, test(union_distinct),
365
 
                                          create_options, ""))
 
355
                                          create_options, "", false))
366
356
      goto err;
367
357
    memset(&result_table_list, 0, sizeof(result_table_list));
368
 
    result_table_list.setSchemaName((char*) "");
369
 
    result_table_list.alias= "union";
370
 
    result_table_list.setTableName((char *) "union");
 
358
    result_table_list.db= (char*) "";
 
359
    result_table_list.table_name= result_table_list.alias= (char*) "union";
371
360
    result_table_list.table= table= union_result->table;
372
361
 
373
 
    session_arg->getLex()->current_select= lex_select_save;
 
362
    session_arg->lex->current_select= lex_select_save;
374
363
    if (!item_list.elements)
375
364
    {
376
365
      saved_error= table->fill_item_list(&item_list);
387
376
    }
388
377
  }
389
378
 
390
 
  session_arg->getLex()->current_select= lex_select_save;
 
379
  session_arg->lex->current_select= lex_select_save;
391
380
 
392
381
  return(saved_error || session_arg->is_fatal_error);
393
382
 
394
383
err:
395
 
  session_arg->getLex()->current_select= lex_select_save;
 
384
  session_arg->lex->current_select= lex_select_save;
396
385
  return(true);
397
386
}
398
387
 
399
388
 
400
389
bool Select_Lex_Unit::exec()
401
390
{
402
 
  Select_Lex *lex_select_save= session->getLex()->current_select;
 
391
  Select_Lex *lex_select_save= session->lex->current_select;
403
392
  Select_Lex *select_cursor=first_select();
404
393
  uint64_t add_rows=0;
405
394
  ha_rows examined_rows= 0;
406
395
 
407
 
  if (executed && uncacheable.none() && ! describe)
408
 
    return false;
 
396
  if (executed && !uncacheable && !describe)
 
397
    return(false);
409
398
  executed= 1;
410
399
 
411
 
  if (uncacheable.any() || ! item || ! item->assigned() || describe)
 
400
  if (uncacheable || !item || !item->assigned() || describe)
412
401
  {
413
402
    if (item)
414
403
      item->reset_value_registration();
418
407
      {
419
408
        item->assigned(0); // We will reinit & rexecute unit
420
409
        item->reset();
421
 
        table->cursor->ha_delete_all_rows();
 
410
        table->file->ha_delete_all_rows();
422
411
      }
423
412
      /* re-enabling indexes for next subselect iteration */
424
 
      if (union_distinct && table->cursor->ha_enable_indexes(HA_KEY_SWITCH_ALL))
 
413
      if (union_distinct && table->file->ha_enable_indexes(HA_KEY_SWITCH_ALL))
425
414
      {
426
415
        assert(0);
427
416
      }
429
418
    for (Select_Lex *sl= select_cursor; sl; sl= sl->next_select())
430
419
    {
431
420
      ha_rows records_at_start= 0;
432
 
      session->getLex()->current_select= sl;
 
421
      session->lex->current_select= sl;
433
422
 
434
423
      if (optimized)
435
424
        saved_error= sl->join->reinit();
440
429
        {
441
430
          offset_limit_cnt= 0;
442
431
          /*
443
 
            We can't use LIMIT at this stage if we are using ORDER BY for the
 
432
            We can't use LIMIT at this stage if we are using order_st BY for the
444
433
            whole query
445
434
          */
446
435
          if (sl->order_list.first || describe)
456
445
          (select_limit_cnt == HA_POS_ERROR || sl->braces) ?
457
446
          sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
458
447
 
 
448
        if (sl->join->flatten_subqueries())
 
449
          return(true);
 
450
 
459
451
        saved_error= sl->join->optimize();
460
452
      }
461
453
      if (!saved_error)
462
454
      {
463
 
        records_at_start= table->cursor->stats.records;
 
455
        records_at_start= table->file->stats.records;
464
456
        sl->join->exec();
465
457
        if (sl == union_distinct)
466
458
        {
467
 
          if (table->cursor->ha_disable_indexes(HA_KEY_SWITCH_ALL))
 
459
          if (table->file->ha_disable_indexes(HA_KEY_SWITCH_ALL))
468
460
            return(true);
469
461
          table->no_keyread=1;
470
462
        }
477
469
          examined_rows+= session->examined_row_count;
478
470
          if (union_result->flush())
479
471
          {
480
 
            session->getLex()->current_select= lex_select_save;
 
472
            session->lex->current_select= lex_select_save;
481
473
            return(1);
482
474
          }
483
475
        }
484
476
      }
485
477
      if (saved_error)
486
478
      {
487
 
        session->getLex()->current_select= lex_select_save;
 
479
        session->lex->current_select= lex_select_save;
488
480
        return(saved_error);
489
481
      }
490
482
      /* Needed for the following test and for records_at_start in next loop */
491
 
      int error= table->cursor->info(HA_STATUS_VARIABLE);
492
 
      if (error)
 
483
      int error= table->file->info(HA_STATUS_VARIABLE);
 
484
      if(error)
493
485
      {
494
 
        table->print_error(error, MYF(0));
 
486
        table->file->print_error(error, MYF(0));
495
487
        return(1);
496
488
      }
497
489
      if (found_rows_for_union && !sl->braces &&
504
496
          rows and actual rows added to the temporary table.
505
497
        */
506
498
        add_rows+= (uint64_t) (session->limit_found_rows - (uint64_t)
507
 
                              ((table->cursor->stats.records -  records_at_start)));
 
499
                              ((table->file->stats.records -  records_at_start)));
508
500
      }
509
501
    }
510
502
  }
517
509
    {
518
510
      set_limit(global_parameters);
519
511
      init_prepare_fake_select_lex(session);
520
 
      Join *join= fake_select_lex->join;
 
512
      JOIN *join= fake_select_lex->join;
521
513
      if (!join)
522
514
      {
523
515
        /*
524
516
          allocate JOIN for fake select only once (prevent
525
 
          select_query automatic allocation)
526
 
          TODO: The above is nonsense. select_query() will not allocate the
 
517
          mysql_select automatic allocation)
 
518
          TODO: The above is nonsense. mysql_select() will not allocate the
527
519
          join if one already exists. There must be some other reason why we
528
520
          don't let it allocate the join. Perhaps this is because we need
529
521
          some special parameter values passed to join constructor?
530
522
        */
531
 
        if (!(fake_select_lex->join= new Join(session, item_list,
 
523
        if (!(fake_select_lex->join= new JOIN(session, item_list,
532
524
                                              fake_select_lex->options, result)))
533
525
        {
534
 
          fake_select_lex->table_list.clear();
 
526
          fake_select_lex->table_list.empty();
535
527
          return(true);
536
528
        }
537
529
        fake_select_lex->join->no_const_tables= true;
541
533
          allocation.
542
534
        */
543
535
        fake_select_lex->item_list= item_list;
544
 
        saved_error= select_query(session, &fake_select_lex->ref_pointer_array,
 
536
        saved_error= mysql_select(session, &fake_select_lex->ref_pointer_array,
545
537
                              &result_table_list,
546
538
                              0, item_list, NULL,
547
539
                              global_parameters->order_list.elements,
548
 
                              (Order*)global_parameters->order_list.first,
549
 
                              (Order*) NULL, NULL,
 
540
                              (order_st*)global_parameters->order_list.first,
 
541
                              (order_st*) NULL, NULL,
550
542
                              fake_select_lex->options | SELECT_NO_UNLOCK,
551
543
                              result, this, fake_select_lex);
552
544
      }
563
555
            subquery execution rather than EXPLAIN line production. In order
564
556
            to reset them back, we re-do all of the actions (yes it is ugly):
565
557
          */
566
 
                join->reset(session, item_list, fake_select_lex->options, result);
567
 
          saved_error= select_query(session, &fake_select_lex->ref_pointer_array,
 
558
          join->init(session, item_list, fake_select_lex->options, result);
 
559
          saved_error= mysql_select(session, &fake_select_lex->ref_pointer_array,
568
560
                                &result_table_list,
569
561
                                0, item_list, NULL,
570
562
                                global_parameters->order_list.elements,
571
 
                                (Order*)global_parameters->order_list.first,
572
 
                                (Order*) NULL, NULL,
 
563
                                (order_st*)global_parameters->order_list.first,
 
564
                                (order_st*) NULL, NULL,
573
565
                                fake_select_lex->options | SELECT_NO_UNLOCK,
574
566
                                result, this, fake_select_lex);
575
567
        }
581
573
        }
582
574
      }
583
575
 
584
 
      fake_select_lex->table_list.clear();
 
576
      fake_select_lex->table_list.empty();
585
577
      if (!saved_error)
586
578
      {
587
 
        session->limit_found_rows = (uint64_t)table->cursor->stats.records + add_rows;
 
579
        session->limit_found_rows = (uint64_t)table->file->stats.records + add_rows;
588
580
        session->examined_row_count+= examined_rows;
589
581
      }
590
582
      /*
593
585
      */
594
586
    }
595
587
  }
596
 
  session->getLex()->current_select= lex_select_save;
 
588
  session->lex->current_select= lex_select_save;
597
589
  return(saved_error);
598
590
}
599
591
 
610
602
 
611
603
  if (union_result)
612
604
  {
613
 
    safe_delete(union_result);
 
605
    delete union_result;
 
606
    union_result=0; // Safety
 
607
    if (table)
 
608
      table->free_tmp_table(session);
614
609
    table= 0; // Safety
615
610
  }
616
611
 
619
614
 
620
615
  if (fake_select_lex)
621
616
  {
622
 
    Join *join;
 
617
    JOIN *join;
623
618
    if ((join= fake_select_lex->join))
624
619
    {
625
620
      join->tables_list= 0;
628
623
    error|= fake_select_lex->cleanup();
629
624
    if (fake_select_lex->order_list.elements)
630
625
    {
631
 
      Order *ord;
632
 
      for (ord= (Order*)fake_select_lex->order_list.first; ord; ord= ord->next)
 
626
      order_st *ord;
 
627
      for (ord= (order_st*)fake_select_lex->order_list.first; ord; ord= ord->next)
633
628
        (*ord->item)->cleanup();
634
629
    }
635
630
  }
712
707
  {
713
708
    assert((Select_Lex*)join->select_lex == this);
714
709
    error= join->destroy();
715
 
    safe_delete(join);
 
710
    delete join;
 
711
    join= 0;
716
712
  }
717
713
  for (Select_Lex_Unit *lex_unit= first_inner_unit(); lex_unit ;
718
714
       lex_unit= lex_unit->next_unit())
719
715
  {
720
716
    error= (bool) ((uint32_t) error | (uint32_t) lex_unit->cleanup());
721
717
  }
722
 
  non_agg_fields.clear();
723
 
  inner_refs_list.clear();
 
718
  non_agg_fields.empty();
 
719
  inner_refs_list.empty();
724
720
  return(error);
725
721
}
726
722
 
737
733
    for (sl= unit->first_select(); sl; sl= sl->next_select())
738
734
      sl->cleanup_all_joins(full);
739
735
}
740
 
 
741
 
} /* namespace drizzled */