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 */
18
18
UNION's were introduced by Monty and Sinisa <sinisa@mysql.com>
20
#include <drizzled/server_includes.h>
21
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>
30
bool drizzle_union(Session *session, LEX *, select_result *result,
31
Select_Lex_Unit *unit, uint64_t setup_tables_done_option)
22
#include <drizzled/drizzled_error_messages.h>
24
bool mysql_union(THD *thd,
25
LEX *lex __attribute__((unused)),
26
select_result *result,
27
SELECT_LEX_UNIT *unit, ulong setup_tables_done_option)
34
if (!(res= unit->prepare(session, result, SELECT_NO_UNLOCK |
30
if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK |
35
31
setup_tables_done_option)))
44
40
** store records in temporary table for UNION
45
41
***************************************************************************/
47
int select_union::prepare(List<Item> &, Select_Lex_Unit *u)
43
int select_union::prepare(List<Item> &list __attribute__((unused)),
59
56
unit->offset_limit_cnt--;
62
fill_record(session, table->getFields(), values, true);
63
if (session->is_error())
59
fill_record(thd, table->field, values, 1);
66
if ((error= table->cursor->insertRecord(table->getInsertRecord())))
63
if ((error= table->file->ha_write_row(table->record[0])))
68
65
/* create_myisam_from_heap will generate error if needed */
69
if (table->cursor->is_fatal_error(error, HA_CHECK_DUP))
71
my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
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))
85
81
bool select_union::flush()
88
if ((error=table->cursor->extra(HA_EXTRA_NO_CACHE)))
84
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
90
table->print_error(error, MYF(0));
86
table->file->print_error(error, MYF(0));
100
96
select_union::create_result_table()
101
session thread handle
102
98
column_types a list of items used to define columns of the
104
100
is_union_distinct if set, the temporary table will eliminate
105
101
duplicates on insert
106
102
options create options
107
103
table_alias name of the temporary table
104
bit_fields_as_long convert bit fields to uint64_t
110
107
Create a temporary table that is used to store the result of a UNION,
119
select_union::create_result_table(Session *session_arg, List<Item> *column_types,
116
select_union::create_result_table(THD *thd_arg, List<Item> *column_types,
120
117
bool is_union_distinct, uint64_t options,
121
const char *table_alias)
118
const char *table_alias,
119
bool bit_fields_as_long)
123
assert(table == NULL);
124
122
tmp_table_param.init();
125
123
tmp_table_param.field_count= column_types->elements;
124
tmp_table_param.bit_fields_as_long= bit_fields_as_long;
127
if (! (table= create_tmp_table(session_arg, &tmp_table_param, *column_types,
128
(Order*) NULL, is_union_distinct, 1,
126
if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
127
(order_st*) 0, is_union_distinct, 1,
129
128
options, HA_POS_ERROR, (char*) table_alias)))
134
table->cursor->extra(HA_EXTRA_WRITE_CACHE);
135
table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
130
table->file->extra(HA_EXTRA_WRITE_CACHE);
131
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
148
143
void select_union::cleanup()
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();
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);
158
153
initialization procedures before fake_select_lex preparation()
161
Select_Lex_Unit::init_prepare_fake_select_lex()
162
session - thread handler
156
st_select_lex_unit::init_prepare_fake_select_lex()
165
160
options of SELECT
169
Select_Lex_Unit::init_prepare_fake_select_lex(Session *session_arg)
164
st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg)
171
session_arg->lex->current_select= fake_select_lex;
172
fake_select_lex->table_list.link_in_list((unsigned char *)&result_table_list,
166
thd_arg->lex->current_select= fake_select_lex;
167
fake_select_lex->table_list.link_in_list((uchar *)&result_table_list,
174
169
&result_table_list.next_local);
175
fake_select_lex->context.table_list=
176
fake_select_lex->context.first_name_resolution_table=
170
fake_select_lex->context.table_list=
171
fake_select_lex->context.first_name_resolution_table=
177
172
fake_select_lex->get_table_list();
179
for (Order *order= (Order *) global_parameters->order_list.first;
182
order->item= &order->item_ptr;
184
for (Order *order= (Order *)global_parameters->order_list.first;
173
if (!fake_select_lex->first_execution)
175
for (order_st *order= (order_st *) global_parameters->order_list.first;
178
order->item= &order->item_ptr;
180
for (order_st *order= (order_st *)global_parameters->order_list.first;
186
182
order=order->next)
188
184
(*order->item)->walk(&Item::change_context_processor, 0,
189
(unsigned char*) &fake_select_lex->context);
185
(uchar*) &fake_select_lex->context);
194
bool Select_Lex_Unit::prepare(Session *session_arg, select_result *sel_result,
195
uint64_t additional_options)
190
bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
191
uint32_t additional_options)
197
Select_Lex *lex_select_save= session_arg->lex->current_select;
198
Select_Lex *sl, *first_sl= first_select();
193
SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
194
SELECT_LEX *sl, *first_sl= first_select();
199
195
select_result *tmp_result;
200
196
bool is_union_select;
201
197
Table *empty_table= 0;
254
250
bool can_skip_order_by;
255
251
sl->options|= SELECT_NO_UNLOCK;
256
Join *join= new Join(session_arg, sl->item_list,
257
sl->options | session_arg->options | additional_options,
252
JOIN *join= new JOIN(thd_arg, sl->item_list,
253
sl->options | thd_arg->options | additional_options,
260
256
setup_tables_done_option should be set only for very first SELECT,
278
274
sl->order_list.elements) +
279
275
sl->group_list.elements,
280
276
can_skip_order_by ?
281
(Order*) NULL : (Order *)sl->order_list.first,
282
(Order*) sl->group_list.first,
277
(order_st*) 0 : (order_st *)sl->order_list.first,
278
(order_st*) sl->group_list.first,
280
(is_union_select ? (order_st*) 0 :
281
(order_st*) thd_arg->lex->proc_list.first),
285
283
/* There are no * in the statement anymore (for PS) */
286
284
sl->with_wild= 0;
288
if (saved_error || (saved_error= session_arg->is_fatal_error))
286
if (saved_error || (saved_error= thd_arg->is_fatal_error))
291
289
Use items list of underlaid select for derived tables to preserve
302
300
field object without table.
304
302
assert(!empty_table);
305
empty_table= (Table*) session->calloc(sizeof(Table));
303
empty_table= (Table*) thd->calloc(sizeof(Table));
307
305
List_iterator_fast<Item> it(sl->item_list);
309
307
while ((item_tmp= it++))
311
309
/* Error's in 'new' will be detected after loop */
312
types.push_back(new Item_type_holder(session_arg, item_tmp));
310
types.push_back(new Item_type_holder(thd_arg, item_tmp));
315
if (session_arg->is_fatal_error)
313
if (thd_arg->is_fatal_error)
316
314
goto err; // out of memory
326
324
List_iterator_fast<Item> it(sl->item_list);
327
List_iterator_fast<Item> tp(types);
325
List_iterator_fast<Item> tp(types);
328
326
Item *type, *item_tmp;
329
327
while ((type= tp++, item_tmp= it++))
331
if (((Item_type_holder*)type)->join_types(session_arg, item_tmp))
329
if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
357
create_options= (first_sl->options | session_arg->options |
355
create_options= (first_sl->options | thd_arg->options |
358
356
TMP_TABLE_ALL_COLUMNS);
360
if (union_result->create_result_table(session, &types, test(union_distinct),
358
if (union_result->create_result_table(thd, &types, test(union_distinct),
359
create_options, "", false))
363
361
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");
362
result_table_list.db= (char*) "";
363
result_table_list.table_name= result_table_list.alias= (char*) "union";
367
364
result_table_list.table= table= union_result->table;
369
session_arg->lex->current_select= lex_select_save;
366
thd_arg->lex->current_select= lex_select_save;
370
367
if (!item_list.elements)
372
369
saved_error= table->fill_item_list(&item_list);
375
assert(thd->stmt_arena->is_conventional() == false);
379
377
We're in execution of a prepared statement or stored procedure:
380
378
reset field items to point at fields from the created temporary table.
380
table->reset_item_list(&item_list);
386
session_arg->lex->current_select= lex_select_save;
384
thd_arg->lex->current_select= lex_select_save;
388
return(saved_error || session_arg->is_fatal_error);
386
return(saved_error || thd_arg->is_fatal_error);
391
session_arg->lex->current_select= lex_select_save;
389
thd_arg->lex->current_select= lex_select_save;
396
bool Select_Lex_Unit::exec()
394
bool st_select_lex_unit::exec()
398
Select_Lex *lex_select_save= session->lex->current_select;
399
Select_Lex *select_cursor=first_select();
396
SELECT_LEX *lex_select_save= thd->lex->current_select;
397
SELECT_LEX *select_cursor=first_select();
400
398
uint64_t add_rows=0;
401
399
ha_rows examined_rows= 0;
403
if (executed && uncacheable.none() && ! describe)
401
if (executed && !uncacheable && !describe)
407
if (uncacheable.any() || ! item || ! item->assigned() || describe)
405
if (uncacheable || !item || !item->assigned() || describe)
410
408
item->reset_value_registration();
415
413
item->assigned(0); // We will reinit & rexecute unit
417
table->cursor->ha_delete_all_rows();
415
table->file->ha_delete_all_rows();
419
417
/* re-enabling indexes for next subselect iteration */
420
if (union_distinct && table->cursor->ha_enable_indexes(HA_KEY_SWITCH_ALL))
418
if (union_distinct && table->file->ha_enable_indexes(HA_KEY_SWITCH_ALL))
425
for (Select_Lex *sl= select_cursor; sl; sl= sl->next_select())
423
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
427
425
ha_rows records_at_start= 0;
428
session->lex->current_select= sl;
426
thd->lex->current_select= sl;
431
429
saved_error= sl->join->reinit();
448
446
we don't calculate found_rows() per union part.
449
447
Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
451
sl->join->select_options=
449
sl->join->select_options=
452
450
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
453
451
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
453
/* dump_TableList_struct(select_lex, select_lex->leaf_tables); */
454
if (sl->join->flatten_subqueries())
457
/* dump_TableList_struct(select_lex, select_lex->leaf_tables); */
455
458
saved_error= sl->join->optimize();
457
460
if (!saved_error)
459
records_at_start= table->cursor->stats.records;
462
records_at_start= table->file->stats.records;
460
463
sl->join->exec();
461
464
if (sl == union_distinct)
463
if (table->cursor->ha_disable_indexes(HA_KEY_SWITCH_ALL))
466
if (table->file->ha_disable_indexes(HA_KEY_SWITCH_ALL))
465
468
table->no_keyread=1;
471
474
if (!saved_error)
473
examined_rows+= session->examined_row_count;
476
examined_rows+= thd->examined_row_count;
474
477
if (union_result->flush())
476
session->lex->current_select= lex_select_save;
479
thd->lex->current_select= lex_select_save;
483
session->lex->current_select= lex_select_save;
486
thd->lex->current_select= lex_select_save;
484
487
return(saved_error);
486
489
/* Needed for the following test and for records_at_start in next loop */
487
int error= table->cursor->info(HA_STATUS_VARIABLE);
490
int error= table->file->info(HA_STATUS_VARIABLE);
490
table->print_error(error, MYF(0));
493
table->file->print_error(error, MYF(0));
493
if (found_rows_for_union && !sl->braces &&
496
if (found_rows_for_union && !sl->braces &&
494
497
select_limit_cnt != HA_POS_ERROR)
499
502
We get this from the difference of between total number of possible
500
503
rows and actual rows added to the temporary table.
502
add_rows+= (uint64_t) (session->limit_found_rows - (uint64_t)
503
((table->cursor->stats.records - records_at_start)));
505
add_rows+= (uint64_t) (thd->limit_found_rows - (uint64_t)
506
((table->file->stats.records - records_at_start)));
509
512
/* Send result to 'result' */
510
513
saved_error= true;
512
if (!session->is_fatal_error) // Check if EOM
515
if (!thd->is_fatal_error) // Check if EOM
514
517
set_limit(global_parameters);
515
init_prepare_fake_select_lex(session);
516
Join *join= fake_select_lex->join;
518
init_prepare_fake_select_lex(thd);
519
JOIN *join= fake_select_lex->join;
520
523
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
524
mysql_select automatic allocation)
525
TODO: The above is nonsense. mysql_select() will not allocate the
523
526
join if one already exists. There must be some other reason why we
524
527
don't let it allocate the join. Perhaps this is because we need
525
528
some special parameter values passed to join constructor?
527
if (!(fake_select_lex->join= new Join(session, item_list,
530
if (!(fake_select_lex->join= new JOIN(thd, item_list,
528
531
fake_select_lex->options, result)))
530
533
fake_select_lex->table_list.empty();
533
536
fake_select_lex->join->no_const_tables= true;
536
Fake Select_Lex should have item list for correctref_array
539
Fake st_select_lex should have item list for correctref_array
539
542
fake_select_lex->item_list= item_list;
540
saved_error= select_query(session, &fake_select_lex->ref_pointer_array,
543
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
541
544
&result_table_list,
542
545
0, item_list, NULL,
543
546
global_parameters->order_list.elements,
544
(Order*)global_parameters->order_list.first,
547
(order_st*)global_parameters->order_list.first,
548
(order_st*) NULL, NULL, (order_st*) NULL,
546
549
fake_select_lex->options | SELECT_NO_UNLOCK,
547
550
result, this, fake_select_lex);
556
559
- 1st time is a real evaluation to get the subquery value
557
560
- 2nd time is to produce EXPLAIN output rows.
558
561
1st execution sets certain members (e.g. select_result) to perform
559
subquery execution rather than EXPLAIN line production. In order
562
subquery execution rather than EXPLAIN line production. In order
560
563
to reset them back, we re-do all of the actions (yes it is ugly):
562
join->reset(session, item_list, fake_select_lex->options, result);
563
saved_error= select_query(session, &fake_select_lex->ref_pointer_array,
565
join->init(thd, item_list, fake_select_lex->options, result);
566
saved_error= mysql_select(thd, &fake_select_lex->ref_pointer_array,
564
567
&result_table_list,
565
568
0, item_list, NULL,
566
569
global_parameters->order_list.elements,
567
(Order*)global_parameters->order_list.first,
570
(order_st*)global_parameters->order_list.first,
571
(order_st*) NULL, NULL, (order_st*) NULL,
569
572
fake_select_lex->options | SELECT_NO_UNLOCK,
570
573
result, this, fake_select_lex);
580
583
fake_select_lex->table_list.empty();
581
584
if (!saved_error)
583
session->limit_found_rows = (uint64_t)table->cursor->stats.records + add_rows;
584
session->examined_row_count+= examined_rows;
586
thd->limit_found_rows = (uint64_t)table->file->stats.records + add_rows;
587
thd->examined_row_count+= examined_rows;
587
590
Mark for slow query log if any of the union parts didn't use
609
612
delete union_result;
610
613
union_result=0; // Safety
615
table->free_tmp_table(thd);
611
616
table= 0; // Safety
614
for (Select_Lex *sl= first_select(); sl; sl= sl->next_select())
619
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
615
620
error|= sl->cleanup();
617
622
if (fake_select_lex)
620
625
if ((join= fake_select_lex->join))
622
627
join->tables_list= 0;
645
650
change select_result object of unit
648
Select_Lex_Unit::change_result()
653
st_select_lex_unit::change_result()
649
654
result new select_result object
650
655
old_result old select_result object
657
bool Select_Lex_Unit::change_result(select_result_interceptor *new_result,
662
bool st_select_lex_unit::change_result(select_result_interceptor *new_result,
658
663
select_result_interceptor *old_result)
661
for (Select_Lex *sl= first_select(); sl; sl= sl->next_select())
666
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
663
668
if (sl->join && sl->join->result == old_result)
664
669
if (sl->join->change_result(new_result))
673
678
Get column type information for this unit.
676
Select_Lex_Unit::get_unit_column_types()
681
st_select_lex_unit::get_unit_column_types()
679
684
For a single-select the column types are taken
680
685
from the list of selected items. For a union this function
681
assumes that Select_Lex_Unit::prepare has been called
686
assumes that st_select_lex_unit::prepare has been called
682
687
and returns the type holders that were created for unioned
683
688
column types of all selects.
686
691
The implementation of this function should be in sync with
687
Select_Lex_Unit::prepare()
692
st_select_lex_unit::prepare()
690
List<Item> *Select_Lex_Unit::get_unit_column_types()
695
List<Item> *st_select_lex_unit::get_unit_column_types()
692
Select_Lex *sl= first_select();
697
SELECT_LEX *sl= first_select();
701
706
return &sl->item_list;
704
bool Select_Lex::cleanup()
709
bool st_select_lex::cleanup()
706
711
bool error= false;
710
assert((Select_Lex*)join->select_lex == this);
715
assert((st_select_lex*)join->select_lex == this);
711
716
error= join->destroy();
715
for (Select_Lex_Unit *lex_unit= first_inner_unit(); lex_unit ;
720
for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ;
716
721
lex_unit= lex_unit->next_unit())
718
error= (bool) ((uint32_t) error | (uint32_t) lex_unit->cleanup());
723
error= (bool) ((uint) error | (uint) lex_unit->cleanup());
720
725
non_agg_fields.empty();
721
726
inner_refs_list.empty();