~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_union.cc

  • Committer: Brian Aker
  • Date: 2008-11-04 15:39:09 UTC
  • mfrom: (575.1.2 devel)
  • Revision ID: brian@tangent.org-20081104153909-c72hn65udxs1ccal
Merge of Monty's work

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
*/
20
20
#include <drizzled/server_includes.h>
21
21
#include <drizzled/sql_select.h>
22
 
#include <drizzled/drizzled_error_messages.h>
 
22
#include <drizzled/error.h>
23
23
 
24
 
bool mysql_union(THD *thd,
25
 
                 LEX *lex __attribute__((unused)),
26
 
                 select_result *result,
 
24
bool mysql_union(Session *session, LEX *, select_result *result,
27
25
                 SELECT_LEX_UNIT *unit, ulong setup_tables_done_option)
28
26
{
29
27
  bool res;
30
 
  if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK |
 
28
  if (!(res= unit->prepare(session, result, SELECT_NO_UNLOCK |
31
29
                           setup_tables_done_option)))
32
30
    res= unit->exec();
33
31
  if (res)
40
38
** store records in temporary table for UNION
41
39
***************************************************************************/
42
40
 
43
 
int select_union::prepare(List<Item> &list __attribute__((unused)),
44
 
                          SELECT_LEX_UNIT *u)
 
41
int select_union::prepare(List<Item> &, SELECT_LEX_UNIT *u)
45
42
{
46
43
  unit= u;
47
44
  return 0;
56
53
    unit->offset_limit_cnt--;
57
54
    return 0;
58
55
  }
59
 
  fill_record(thd, table->field, values, 1);
60
 
  if (thd->is_error())
 
56
  fill_record(session, table->field, values, 1);
 
57
  if (session->is_error())
61
58
    return 1;
62
59
 
63
60
  if ((error= table->file->ha_write_row(table->record[0])))
64
61
  {
65
62
    /* create_myisam_from_heap will generate error if needed */
66
63
    if (table->file->is_fatal_error(error, HA_CHECK_DUP) &&
67
 
        create_myisam_from_heap(thd, table, tmp_table_param.start_recinfo, 
 
64
        create_myisam_from_heap(session, table, tmp_table_param.start_recinfo, 
68
65
                                &tmp_table_param.recinfo, error, 1))
69
66
      return 1;
70
67
  }
94
91
 
95
92
  SYNOPSIS
96
93
    select_union::create_result_table()
97
 
      thd                thread handle
 
94
      session                thread handle
98
95
      column_types       a list of items used to define columns of the
99
96
                         temporary table
100
97
      is_union_distinct  if set, the temporary table will eliminate
113
110
*/
114
111
 
115
112
bool
116
 
select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
 
113
select_union::create_result_table(Session *session_arg, List<Item> *column_types,
117
114
                                  bool is_union_distinct, uint64_t options,
118
115
                                  const char *table_alias,
119
116
                                  bool bit_fields_as_long)
123
120
  tmp_table_param.field_count= column_types->elements;
124
121
  tmp_table_param.bit_fields_as_long= bit_fields_as_long;
125
122
 
126
 
  if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
 
123
  if (! (table= create_tmp_table(session_arg, &tmp_table_param, *column_types,
127
124
                                 (order_st*) 0, is_union_distinct, 1,
128
125
                                 options, HA_POS_ERROR, (char*) table_alias)))
129
126
    return true;
154
151
 
155
152
  SYNOPSIS
156
153
    st_select_lex_unit::init_prepare_fake_select_lex()
157
 
    thd         - thread handler
 
154
    session             - thread handler
158
155
 
159
156
  RETURN
160
157
    options of SELECT
161
158
*/
162
159
 
163
160
void
164
 
st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg) 
 
161
st_select_lex_unit::init_prepare_fake_select_lex(Session *session_arg) 
165
162
{
166
 
  thd_arg->lex->current_select= fake_select_lex;
167
 
  fake_select_lex->table_list.link_in_list((uchar *)&result_table_list,
168
 
                                           (uchar **)
 
163
  session_arg->lex->current_select= fake_select_lex;
 
164
  fake_select_lex->table_list.link_in_list((unsigned char *)&result_table_list,
 
165
                                           (unsigned char **)
169
166
                                           &result_table_list.next_local);
170
167
  fake_select_lex->context.table_list= 
171
168
    fake_select_lex->context.first_name_resolution_table= 
172
169
    fake_select_lex->get_table_list();
173
 
  if (!fake_select_lex->first_execution)
174
 
  {
175
 
    for (order_st *order= (order_st *) global_parameters->order_list.first;
176
 
         order;
177
 
         order= order->next)
178
 
      order->item= &order->item_ptr;
179
 
  }
 
170
 
 
171
  for (order_st *order= (order_st *) global_parameters->order_list.first;
 
172
       order;
 
173
       order= order->next)
 
174
    order->item= &order->item_ptr;
 
175
 
180
176
  for (order_st *order= (order_st *)global_parameters->order_list.first;
181
177
       order;
182
178
       order=order->next)
183
179
  {
184
180
    (*order->item)->walk(&Item::change_context_processor, 0,
185
 
                         (uchar*) &fake_select_lex->context);
 
181
                         (unsigned char*) &fake_select_lex->context);
186
182
  }
187
183
}
188
184
 
189
185
 
190
 
bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
 
186
bool st_select_lex_unit::prepare(Session *session_arg, select_result *sel_result,
191
187
                                 uint32_t additional_options)
192
188
{
193
 
  SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
 
189
  SELECT_LEX *lex_select_save= session_arg->lex->current_select;
194
190
  SELECT_LEX *sl, *first_sl= first_select();
195
191
  select_result *tmp_result;
196
192
  bool is_union_select;
227
223
  prepared= 1;
228
224
  saved_error= false;
229
225
  
230
 
  thd_arg->lex->current_select= sl= first_sl;
 
226
  session_arg->lex->current_select= sl= first_sl;
231
227
  found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
232
228
  is_union_select= is_union() || fake_select_lex;
233
229
 
249
245
  {
250
246
    bool can_skip_order_by;
251
247
    sl->options|=  SELECT_NO_UNLOCK;
252
 
    JOIN *join= new JOIN(thd_arg, sl->item_list, 
253
 
                         sl->options | thd_arg->options | additional_options,
 
248
    JOIN *join= new JOIN(session_arg, sl->item_list, 
 
249
                         sl->options | session_arg->options | additional_options,
254
250
                         tmp_result);
255
251
    /*
256
252
      setup_tables_done_option should be set only for very first SELECT,
262
258
    if (!join)
263
259
      goto err;
264
260
 
265
 
    thd_arg->lex->current_select= sl;
 
261
    session_arg->lex->current_select= sl;
266
262
 
267
263
    can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit);
268
264
 
278
274
                               (order_st*) sl->group_list.first,
279
275
                               sl->having,
280
276
                               (is_union_select ? (order_st*) 0 :
281
 
                                (order_st*) thd_arg->lex->proc_list.first),
 
277
                                (order_st*) session_arg->lex->proc_list.first),
282
278
                               sl, this);
283
279
    /* There are no * in the statement anymore (for PS) */
284
280
    sl->with_wild= 0;
285
281
 
286
 
    if (saved_error || (saved_error= thd_arg->is_fatal_error))
 
282
    if (saved_error || (saved_error= session_arg->is_fatal_error))
287
283
      goto err;
288
284
    /*
289
285
      Use items list of underlaid select for derived tables to preserve
300
296
        field object without table.
301
297
      */
302
298
      assert(!empty_table);
303
 
      empty_table= (Table*) thd->calloc(sizeof(Table));
 
299
      empty_table= (Table*) session->calloc(sizeof(Table));
304
300
      types.empty();
305
301
      List_iterator_fast<Item> it(sl->item_list);
306
302
      Item *item_tmp;
307
303
      while ((item_tmp= it++))
308
304
      {
309
305
        /* Error's in 'new' will be detected after loop */
310
 
        types.push_back(new Item_type_holder(thd_arg, item_tmp));
 
306
        types.push_back(new Item_type_holder(session_arg, item_tmp));
311
307
      }
312
308
 
313
 
      if (thd_arg->is_fatal_error)
 
309
      if (session_arg->is_fatal_error)
314
310
        goto err; // out of memory
315
311
    }
316
312
    else
326
322
      Item *type, *item_tmp;
327
323
      while ((type= tp++, item_tmp= it++))
328
324
      {
329
 
        if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
 
325
        if (((Item_type_holder*)type)->join_types(session_arg, item_tmp))
330
326
          return(true);
331
327
      }
332
328
    }
352
348
      }
353
349
    }
354
350
    
355
 
    create_options= (first_sl->options | thd_arg->options |
 
351
    create_options= (first_sl->options | session_arg->options |
356
352
                     TMP_TABLE_ALL_COLUMNS);
357
353
 
358
 
    if (union_result->create_result_table(thd, &types, test(union_distinct),
 
354
    if (union_result->create_result_table(session, &types, test(union_distinct),
359
355
                                          create_options, "", false))
360
356
      goto err;
361
357
    memset(&result_table_list, 0, sizeof(result_table_list));
363
359
    result_table_list.table_name= result_table_list.alias= (char*) "union";
364
360
    result_table_list.table= table= union_result->table;
365
361
 
366
 
    thd_arg->lex->current_select= lex_select_save;
 
362
    session_arg->lex->current_select= lex_select_save;
367
363
    if (!item_list.elements)
368
364
    {
369
365
      saved_error= table->fill_item_list(&item_list);
372
368
    }
373
369
    else
374
370
    {
375
 
      assert(thd->stmt_arena->is_conventional() == false);
376
371
      /*
377
372
        We're in execution of a prepared statement or stored procedure:
378
373
        reset field items to point at fields from the created temporary table.
379
374
      */
380
 
      table->reset_item_list(&item_list);
 
375
      assert(1);
381
376
    }
382
377
  }
383
378
 
384
 
  thd_arg->lex->current_select= lex_select_save;
 
379
  session_arg->lex->current_select= lex_select_save;
385
380
 
386
 
  return(saved_error || thd_arg->is_fatal_error);
 
381
  return(saved_error || session_arg->is_fatal_error);
387
382
 
388
383
err:
389
 
  thd_arg->lex->current_select= lex_select_save;
 
384
  session_arg->lex->current_select= lex_select_save;
390
385
  return(true);
391
386
}
392
387
 
393
388
 
394
389
bool st_select_lex_unit::exec()
395
390
{
396
 
  SELECT_LEX *lex_select_save= thd->lex->current_select;
 
391
  SELECT_LEX *lex_select_save= session->lex->current_select;
397
392
  SELECT_LEX *select_cursor=first_select();
398
393
  uint64_t add_rows=0;
399
394
  ha_rows examined_rows= 0;
423
418
    for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
424
419
    {
425
420
      ha_rows records_at_start= 0;
426
 
      thd->lex->current_select= sl;
 
421
      session->lex->current_select= sl;
427
422
 
428
423
      if (optimized)
429
424
        saved_error= sl->join->reinit();
473
468
                                    0);
474
469
        if (!saved_error)
475
470
        {
476
 
          examined_rows+= thd->examined_row_count;
 
471
          examined_rows+= session->examined_row_count;
477
472
          if (union_result->flush())
478
473
          {
479
 
            thd->lex->current_select= lex_select_save;
 
474
            session->lex->current_select= lex_select_save;
480
475
            return(1);
481
476
          }
482
477
        }
483
478
      }
484
479
      if (saved_error)
485
480
      {
486
 
        thd->lex->current_select= lex_select_save;
 
481
        session->lex->current_select= lex_select_save;
487
482
        return(saved_error);
488
483
      }
489
484
      /* Needed for the following test and for records_at_start in next loop */
502
497
          We get this from the difference of between total number of possible
503
498
          rows and actual rows added to the temporary table.
504
499
        */
505
 
        add_rows+= (uint64_t) (thd->limit_found_rows - (uint64_t)
 
500
        add_rows+= (uint64_t) (session->limit_found_rows - (uint64_t)
506
501
                              ((table->file->stats.records -  records_at_start)));
507
502
      }
508
503
    }
512
507
  /* Send result to 'result' */
513
508
  saved_error= true;
514
509
  {
515
 
    if (!thd->is_fatal_error)                           // Check if EOM
 
510
    if (!session->is_fatal_error)                               // Check if EOM
516
511
    {
517
512
      set_limit(global_parameters);
518
 
      init_prepare_fake_select_lex(thd);
 
513
      init_prepare_fake_select_lex(session);
519
514
      JOIN *join= fake_select_lex->join;
520
515
      if (!join)
521
516
      {
527
522
          don't let it allocate the join. Perhaps this is because we need
528
523
          some special parameter values passed to join constructor?
529
524
        */
530
 
        if (!(fake_select_lex->join= new JOIN(thd, item_list,
 
525
        if (!(fake_select_lex->join= new JOIN(session, item_list,
531
526
                                              fake_select_lex->options, result)))
532
527
        {
533
528
          fake_select_lex->table_list.empty();
540
535
          allocation.
541
536
        */
542
537
        fake_select_lex->item_list= item_list;
543
 
        saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
 
538
        saved_error= mysql_select(session, &fake_select_lex->ref_pointer_array,
544
539
                              &result_table_list,
545
540
                              0, item_list, NULL,
546
541
                              global_parameters->order_list.elements,
562
557
            subquery execution rather than EXPLAIN line production. In order 
563
558
            to reset them back, we re-do all of the actions (yes it is ugly):
564
559
          */
565
 
          join->init(thd, item_list, fake_select_lex->options, result);
566
 
          saved_error= mysql_select(thd, &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,
567
562
                                &result_table_list,
568
563
                                0, item_list, NULL,
569
564
                                global_parameters->order_list.elements,
583
578
      fake_select_lex->table_list.empty();
584
579
      if (!saved_error)
585
580
      {
586
 
        thd->limit_found_rows = (uint64_t)table->file->stats.records + add_rows;
587
 
        thd->examined_row_count+= examined_rows;
 
581
        session->limit_found_rows = (uint64_t)table->file->stats.records + add_rows;
 
582
        session->examined_row_count+= examined_rows;
588
583
      }
589
584
      /*
590
585
        Mark for slow query log if any of the union parts didn't use
592
587
      */
593
588
    }
594
589
  }
595
 
  thd->lex->current_select= lex_select_save;
 
590
  session->lex->current_select= lex_select_save;
596
591
  return(saved_error);
597
592
}
598
593
 
612
607
    delete union_result;
613
608
    union_result=0; // Safety
614
609
    if (table)
615
 
      table->free_tmp_table(thd);
 
610
      table->free_tmp_table(session);
616
611
    table= 0; // Safety
617
612
  }
618
613