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>
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>
34
bool drizzle_union(Session *session, LEX *, select_result *result,
35
Select_Lex_Unit *unit, uint64_t setup_tables_done_option)
26
bool mysql_union(Session *session, LEX *, select_result *result,
27
Select_Lex_Unit *unit, uint64_t setup_tables_done_option)
38
30
if (!(res= unit->prepare(session, result, SELECT_NO_UNLOCK |
63
55
unit->offset_limit_cnt--;
66
fill_record(session, table->getFields(), values, true);
58
fill_record(session, table->field, values, 1);
67
59
if (session->is_error())
70
if ((error= table->cursor->insertRecord(table->getInsertRecord())))
62
if ((error= table->file->ha_write_row(table->record[0])))
72
64
/* create_myisam_from_heap will generate error if needed */
73
if (table->cursor->is_fatal_error(error, HA_CHECK_DUP))
75
my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
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))
89
80
bool select_union::flush()
92
if ((error=table->cursor->extra(HA_EXTRA_NO_CACHE)))
83
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
94
table->print_error(error, MYF(0));
85
table->file->print_error(error, MYF(0));
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)
127
assert(table == NULL);
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;
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)))
138
table->cursor->extra(HA_EXTRA_WRITE_CACHE);
139
table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
129
table->file->extra(HA_EXTRA_WRITE_CACHE);
130
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
152
142
void select_union::cleanup()
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);
173
163
Select_Lex_Unit::init_prepare_fake_select_lex(Session *session_arg)
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();
183
for (Order *order= (Order *) global_parameters->order_list.first;
173
for (order_st *order= (order_st *) global_parameters->order_list.first;
185
175
order= order->next)
186
176
order->item= &order->item_ptr;
188
for (Order *order= (Order *)global_parameters->order_list.first;
178
for (order_st *order= (order_st *)global_parameters->order_list.first;
190
180
order=order->next)
198
188
bool Select_Lex_Unit::prepare(Session *session_arg, select_result *sel_result,
199
189
uint64_t additional_options)
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;
236
226
saved_error= false;
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;
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,
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,
289
279
/* There are no * in the statement anymore (for PS) */
327
317
ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
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++))
362
352
TMP_TABLE_ALL_COLUMNS);
364
354
if (union_result->create_result_table(session, &types, test(union_distinct),
355
create_options, "", false))
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;
373
session_arg->getLex()->current_select= lex_select_save;
362
session_arg->lex->current_select= lex_select_save;
374
363
if (!item_list.elements)
376
365
saved_error= table->fill_item_list(&item_list);
390
session_arg->getLex()->current_select= lex_select_save;
379
session_arg->lex->current_select= lex_select_save;
392
381
return(saved_error || session_arg->is_fatal_error);
395
session_arg->getLex()->current_select= lex_select_save;
384
session_arg->lex->current_select= lex_select_save;
400
389
bool Select_Lex_Unit::exec()
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;
407
if (executed && uncacheable.none() && ! describe)
396
if (executed && !uncacheable && !describe)
411
if (uncacheable.any() || ! item || ! item->assigned() || describe)
400
if (uncacheable || !item || !item->assigned() || describe)
414
403
item->reset_value_registration();
419
408
item->assigned(0); // We will reinit & rexecute unit
421
table->cursor->ha_delete_all_rows();
410
table->file->ha_delete_all_rows();
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))
429
418
for (Select_Lex *sl= select_cursor; sl; sl= sl->next_select())
431
420
ha_rows records_at_start= 0;
432
session->getLex()->current_select= sl;
421
session->lex->current_select= sl;
435
424
saved_error= sl->join->reinit();
456
445
(select_limit_cnt == HA_POS_ERROR || sl->braces) ?
457
446
sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
448
if (sl->join->flatten_subqueries())
459
451
saved_error= sl->join->optimize();
461
453
if (!saved_error)
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)
467
if (table->cursor->ha_disable_indexes(HA_KEY_SWITCH_ALL))
459
if (table->file->ha_disable_indexes(HA_KEY_SWITCH_ALL))
469
461
table->no_keyread=1;
477
469
examined_rows+= session->examined_row_count;
478
470
if (union_result->flush())
480
session->getLex()->current_select= lex_select_save;
472
session->lex->current_select= lex_select_save;
487
session->getLex()->current_select= lex_select_save;
479
session->lex->current_select= lex_select_save;
488
480
return(saved_error);
490
482
/* Needed for the following test and for records_at_start in next loop */
491
int error= table->cursor->info(HA_STATUS_VARIABLE);
483
int error= table->file->info(HA_STATUS_VARIABLE);
494
table->print_error(error, MYF(0));
486
table->file->print_error(error, MYF(0));
497
489
if (found_rows_for_union && !sl->braces &&
504
496
rows and actual rows added to the temporary table.
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)));
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;
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?
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)))
534
fake_select_lex->table_list.clear();
526
fake_select_lex->table_list.empty();
537
529
fake_select_lex->join->no_const_tables= true;
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,
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);
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):
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,
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);
584
fake_select_lex->table_list.clear();
576
fake_select_lex->table_list.empty();
585
577
if (!saved_error)
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;
628
623
error|= fake_select_lex->cleanup();
629
624
if (fake_select_lex->order_list.elements)
632
for (ord= (Order*)fake_select_lex->order_list.first; ord; ord= ord->next)
627
for (ord= (order_st*)fake_select_lex->order_list.first; ord; ord= ord->next)
633
628
(*ord->item)->cleanup();
713
708
assert((Select_Lex*)join->select_lex == this);
714
709
error= join->destroy();
717
713
for (Select_Lex_Unit *lex_unit= first_inner_unit(); lex_unit ;
718
714
lex_unit= lex_unit->next_unit())
720
716
error= (bool) ((uint32_t) error | (uint32_t) lex_unit->cleanup());
722
non_agg_fields.clear();
723
inner_refs_list.clear();
718
non_agg_fields.empty();
719
inner_refs_list.empty();