Drizzled Public API Documentation

sql_union.cc
1 /* Copyright (C) 2000-2003 MySQL AB
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
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 */
15 
16 /*
17  UNION of select's
18  UNION's were introduced by Monty and Sinisa <sinisa@mysql.com>
19 */
20 #include <config.h>
21 
22 #include <drizzled/sql_select.h>
23 #include <drizzled/error.h>
24 #include <drizzled/item/type_holder.h>
25 #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 #include <drizzled/item/subselect.h>
31 
32 namespace drizzled {
33 
34 bool drizzle_union(Session *session, LEX *, select_result *result,
35  Select_Lex_Unit *unit, uint64_t setup_tables_done_option)
36 {
37  bool res= unit->prepare(session, result, SELECT_NO_UNLOCK | setup_tables_done_option);
38  if (not res)
39  res= unit->exec();
40  if (res)
41  unit->cleanup();
42  return res;
43 }
44 
45 
46 /***************************************************************************
47 ** store records in temporary table for UNION
48 ***************************************************************************/
49 
50 int select_union::prepare(List<Item> &, Select_Lex_Unit *u)
51 {
52  unit= u;
53  return 0;
54 }
55 
56 
57 bool select_union::send_data(List<Item> &values)
58 {
59  int error= 0;
60  if (unit->offset_limit_cnt)
61  { // using limit offset,count
62  unit->offset_limit_cnt--;
63  return 0;
64  }
65  fill_record(session, table->getFields(), values, true);
66  if (session->is_error())
67  return 1;
68 
69  if ((error= table->cursor->insertRecord(table->getInsertRecord())))
70  {
71  /* create_myisam_from_heap will generate error if needed */
72  if (table->cursor->is_fatal_error(error, HA_CHECK_DUP))
73  {
74  my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
75  return true;
76  }
77  }
78  return 0;
79 }
80 
81 
82 bool select_union::send_eof()
83 {
84  return 0;
85 }
86 
87 
88 bool select_union::flush()
89 {
90  int error;
91  if ((error=table->cursor->extra(HA_EXTRA_NO_CACHE)))
92  {
93  table->print_error(error, MYF(0));
94  return 1;
95  }
96  return 0;
97 }
98 
99 /*
100  Create a temporary table to store the result of select_union.
101 
102  SYNOPSIS
103  select_union::create_result_table()
104  session thread handle
105  column_types a list of items used to define columns of the
106  temporary table
107  is_union_distinct if set, the temporary table will eliminate
108  duplicates on insert
109  options create options
110  table_alias name of the temporary table
111 
112  DESCRIPTION
113  Create a temporary table that is used to store the result of a UNION,
114  derived table, or a materialized cursor.
115 
116  RETURN VALUE
117  0 The table has been created successfully.
118  1 create_tmp_table failed.
119 */
120 
121 bool
122 select_union::create_result_table(Session *session_arg, List<Item> *column_types,
123  bool is_union_distinct, uint64_t options,
124  const char *table_alias)
125 {
126  assert(table == NULL);
127  tmp_table_param.init();
128  tmp_table_param.field_count= column_types->size();
129 
130  if (! (table= create_tmp_table(session_arg, &tmp_table_param, *column_types,
131  (Order*) NULL, is_union_distinct, 1,
132  options, HA_POS_ERROR, (char*) table_alias)))
133  {
134  return true;
135  }
136 
137  table->cursor->extra(HA_EXTRA_WRITE_CACHE);
138  table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
139 
140  return false;
141 }
142 
143 
152 {
153  table->cursor->extra(HA_EXTRA_RESET_STATE);
154  table->cursor->ha_delete_all_rows();
155  table->free_io_cache();
156  table->filesort_free_buffers();
157 }
158 
159 
160 /*
161  initialization procedures before fake_select_lex preparation()
162 
163  SYNOPSIS
164  Select_Lex_Unit::init_prepare_fake_select_lex()
165  session - thread handler
166 
167  RETURN
168  options of SELECT
169 */
170 
171 void
172 Select_Lex_Unit::init_prepare_fake_select_lex(Session *session_arg)
173 {
174  session_arg->lex().current_select= fake_select_lex;
175  fake_select_lex->table_list.link_in_list((unsigned char *)&result_table_list,
176  (unsigned char **)
177  &result_table_list.next_local);
178  fake_select_lex->context.table_list=
179  fake_select_lex->context.first_name_resolution_table=
180  fake_select_lex->get_table_list();
181 
182  for (Order *order= (Order *) global_parameters->order_list.first;
183  order;
184  order= order->next)
185  order->item= &order->item_ptr;
186 
187  for (Order *order= (Order *)global_parameters->order_list.first;
188  order;
189  order=order->next)
190  {
191  (*order->item)->walk(&Item::change_context_processor, 0,
192  (unsigned char*) &fake_select_lex->context);
193  }
194 }
195 
196 
197 bool Select_Lex_Unit::prepare(Session *session_arg, select_result *sel_result,
198  uint64_t additional_options)
199 {
200  Select_Lex *lex_select_save= session_arg->lex().current_select;
201  Select_Lex *sl, *first_sl= first_select();
202  select_result *tmp_result;
203  bool is_union_select;
204  Table *empty_table= 0;
205 
206  describe= test(additional_options & SELECT_DESCRIBE);
207 
208  /*
209  result object should be reassigned even if preparing already done for
210  max/min subquery (ALL/ANY optimization)
211  */
212  result= sel_result;
213 
214  if (prepared)
215  {
216  if (describe)
217  {
218  /* fast reinit for EXPLAIN */
219  for (sl= first_sl; sl; sl= sl->next_select())
220  {
221  sl->join->result= result;
222  select_limit_cnt= HA_POS_ERROR;
223  offset_limit_cnt= 0;
224  if (result->prepare(sl->join->fields_list, this))
225  {
226  return true;
227  }
228  sl->join->select_options|= SELECT_DESCRIBE;
229  sl->join->reinit();
230  }
231  }
232  return false;
233  }
234  prepared= 1;
235  saved_error= false;
236 
237  session_arg->lex().current_select= sl= first_sl;
238  found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
239  is_union_select= is_union() || fake_select_lex;
240 
241  /* Global option */
242 
243  if (is_union_select)
244  {
245  tmp_result= union_result= new select_union;
246  if (describe)
247  tmp_result= sel_result;
248  }
249  else
250  tmp_result= sel_result;
251 
252  sl->context.resolve_in_select_list= true;
253 
254  for (;sl; sl= sl->next_select())
255  {
256  bool can_skip_order_by;
257  sl->options|= SELECT_NO_UNLOCK;
258  Join *join= new Join(session_arg, sl->item_list,
259  sl->options | session_arg->options | additional_options,
260  tmp_result);
261  /*
262  setup_tables_done_option should be set only for very first SELECT,
263  because it protect from secont setup_tables call for select-like non
264  select commands (DELETE/INSERT/...) and they use only very first
265  SELECT (for union it can be only INSERT ... SELECT).
266  */
267  additional_options&= ~OPTION_SETUP_TABLES_DONE;
268  if (!join)
269  goto err;
270 
271  session_arg->lex().current_select= sl;
272 
273  can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit);
274 
275  saved_error= join->prepare(&sl->ref_pointer_array,
276  (TableList*) sl->table_list.first,
277  sl->with_wild,
278  sl->where,
279  (can_skip_order_by ? 0 :
280  sl->order_list.size()) +
281  sl->group_list.size(),
282  can_skip_order_by ?
283  (Order*) NULL : (Order *)sl->order_list.first,
284  (Order*) sl->group_list.first,
285  sl->having,
286  sl, this);
287  /* There are no * in the statement anymore (for PS) */
288  sl->with_wild= 0;
289 
290  if (saved_error || (saved_error= session_arg->is_fatal_error))
291  goto err;
292  /*
293  Use items list of underlaid select for derived tables to preserve
294  information about fields lengths and exact types
295  */
296  if (!is_union_select)
297  {
298  types= first_sl->item_list;
299  }
300  else if (sl == first_sl)
301  {
302  /*
303  We need to create an empty table object. It is used
304  to create tmp_table fields in Item_type_holder.
305  The main reason of this is that we can't create
306  field object without table.
307  */
308  (void)(empty_table);
309  assert(!empty_table);
310  empty_table= (Table*) session->mem.calloc(sizeof(Table));
311  types.clear();
312  List<Item>::iterator it(sl->item_list.begin());
313  while (Item* item_tmp= it++)
314  {
315  /* Error's in 'new' will be detected after loop */
316  types.push_back(new Item_type_holder(session_arg, item_tmp));
317  }
318 
319  if (session_arg->is_fatal_error)
320  goto err; // out of memory
321  }
322  else
323  {
324  if (types.size() != sl->item_list.size())
325  {
326  my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
327  ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
328  goto err;
329  }
330  List<Item>::iterator it(sl->item_list.begin());
331  List<Item>::iterator tp(types.begin());
332  Item *type, *item_tmp;
333  while ((type= tp++, item_tmp= it++))
334  {
335  if (((Item_type_holder*)type)->join_types(session_arg, item_tmp))
336  return true;
337  }
338  }
339  }
340 
341  if (is_union_select)
342  {
343  /*
344  Check that it was possible to aggregate
345  all collations together for UNION.
346  */
347  List<Item>::iterator tp(types.begin());
348  Item *type;
349  uint64_t create_options;
350 
351  while ((type= tp++))
352  {
353  if (type->result_type() == STRING_RESULT &&
354  type->collation.derivation == DERIVATION_NONE)
355  {
356  my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), "UNION");
357  goto err;
358  }
359  }
360 
361  create_options= first_sl->options | session_arg->options | TMP_TABLE_ALL_COLUMNS;
362 
363  if (union_result->create_result_table(session, &types, test(union_distinct), create_options, ""))
364  goto err;
365  memset(&result_table_list, 0, sizeof(result_table_list));
366  result_table_list.setSchemaName("");
367  result_table_list.alias= "union";
368  result_table_list.setTableName("union");
369  result_table_list.table= table= union_result->table;
370 
371  session_arg->lex().current_select= lex_select_save;
372  if (item_list.is_empty())
373  table->fill_item_list(item_list);
374  else
375  {
376  /*
377  We're in execution of a prepared statement or stored procedure:
378  reset field items to point at fields from the created temporary table.
379  */
380  assert(false);
381  }
382  }
383 
384  session_arg->lex().current_select= lex_select_save;
385 
386  return(saved_error || session_arg->is_fatal_error);
387 
388 err:
389  session_arg->lex().current_select= lex_select_save;
390  return true;
391 }
392 
393 
394 bool Select_Lex_Unit::exec()
395 {
396  Select_Lex *lex_select_save= session->lex().current_select;
397  Select_Lex *select_cursor=first_select();
398  uint64_t add_rows=0;
399  ha_rows examined_rows= 0;
400 
401  if (executed && uncacheable.none() && ! describe)
402  return false;
403  executed= 1;
404 
405  if (uncacheable.any() || ! item || ! item->assigned() || describe)
406  {
407  if (item)
408  item->reset_value_registration();
409  if (optimized && item)
410  {
411  if (item->assigned())
412  {
413  item->assigned(0); // We will reinit & rexecute unit
414  item->reset();
415  table->cursor->ha_delete_all_rows();
416  }
417  /* re-enabling indexes for next subselect iteration */
418  if (union_distinct && table->cursor->ha_enable_indexes(HA_KEY_SWITCH_ALL))
419  {
420  assert(0);
421  }
422  }
423  for (Select_Lex *sl= select_cursor; sl; sl= sl->next_select())
424  {
425  ha_rows records_at_start= 0;
426  session->lex().current_select= sl;
427 
428  if (optimized)
429  saved_error= sl->join->reinit();
430  else
431  {
432  set_limit(sl);
433  if (sl == global_parameters || describe)
434  {
435  offset_limit_cnt= 0;
436  /*
437  We can't use LIMIT at this stage if we are using ORDER BY for the
438  whole query
439  */
440  if (sl->order_list.first || describe)
441  select_limit_cnt= HA_POS_ERROR;
442  }
443 
444  /*
445  When using braces, SQL_CALC_FOUND_ROWS affects the whole query:
446  we don't calculate found_rows() per union part.
447  Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
448  */
449  sl->join->select_options=
450  (select_limit_cnt == HA_POS_ERROR || sl->braces) ?
451  sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
452 
453  saved_error= sl->join->optimize();
454  }
455  if (!saved_error)
456  {
457  records_at_start= table->cursor->stats.records;
458  sl->join->exec();
459  if (sl == union_distinct)
460  {
461  if (table->cursor->ha_disable_indexes(HA_KEY_SWITCH_ALL))
462  return true;
463  table->no_keyread=1;
464  }
465  saved_error= sl->join->error;
466  offset_limit_cnt= (ha_rows)(sl->offset_limit ?
467  sl->offset_limit->val_uint() :
468  0);
469  if (!saved_error)
470  {
471  examined_rows+= session->examined_row_count;
472  if (union_result->flush())
473  {
474  session->lex().current_select= lex_select_save;
475  return 1;
476  }
477  }
478  }
479  if (saved_error)
480  {
481  session->lex().current_select= lex_select_save;
482  return(saved_error);
483  }
484  /* Needed for the following test and for records_at_start in next loop */
485  int error= table->cursor->info(HA_STATUS_VARIABLE);
486  if (error)
487  {
488  table->print_error(error, MYF(0));
489  return 1;
490  }
491  if (found_rows_for_union && !sl->braces &&
492  select_limit_cnt != HA_POS_ERROR)
493  {
494  /*
495  This is a union without braces. Remember the number of rows that
496  could also have been part of the result set.
497  We get this from the difference of between total number of possible
498  rows and actual rows added to the temporary table.
499  */
500  add_rows+= (uint64_t) (session->limit_found_rows - (uint64_t)
501  ((table->cursor->stats.records - records_at_start)));
502  }
503  }
504  }
505  optimized= 1;
506 
507  /* Send result to 'result' */
508  saved_error= true;
509  {
510  if (!session->is_fatal_error) // Check if EOM
511  {
512  set_limit(global_parameters);
513  init_prepare_fake_select_lex(session);
514  Join *join= fake_select_lex->join;
515  if (!join)
516  {
517  /*
518  allocate JOIN for fake select only once (prevent
519  select_query automatic allocation)
520  TODO: The above is nonsense. select_query() will not allocate the
521  join if one already exists. There must be some other reason why we
522  don't let it allocate the join. Perhaps this is because we need
523  some special parameter values passed to join constructor?
524  */
525  fake_select_lex->join= new Join(session, item_list, fake_select_lex->options, result);
526  fake_select_lex->join->no_const_tables= true;
527 
528  /*
529  Fake Select_Lex should have item list for correctref_array
530  allocation.
531  */
532  fake_select_lex->item_list= item_list;
533  saved_error= select_query(session, &fake_select_lex->ref_pointer_array,
534  &result_table_list,
535  0, item_list, NULL,
536  global_parameters->order_list.size(),
537  (Order*)global_parameters->order_list.first,
538  (Order*) NULL, NULL,
539  fake_select_lex->options | SELECT_NO_UNLOCK,
540  result, this, fake_select_lex);
541  }
542  else
543  {
544  if (describe)
545  {
546  /*
547  In EXPLAIN command, constant subqueries that do not use any
548  tables are executed two times:
549  - 1st time is a real evaluation to get the subquery value
550  - 2nd time is to produce EXPLAIN output rows.
551  1st execution sets certain members (e.g. select_result) to perform
552  subquery execution rather than EXPLAIN line production. In order
553  to reset them back, we re-do all of the actions (yes it is ugly):
554  */
555  join->reset(session, item_list, fake_select_lex->options, result);
556  saved_error= select_query(session, &fake_select_lex->ref_pointer_array,
557  &result_table_list,
558  0, item_list, NULL,
559  global_parameters->order_list.size(),
560  (Order*)global_parameters->order_list.first,
561  (Order*) NULL, NULL,
562  fake_select_lex->options | SELECT_NO_UNLOCK,
563  result, this, fake_select_lex);
564  }
565  else
566  {
567  join->examined_rows= 0;
568  saved_error= join->reinit();
569  join->exec();
570  }
571  }
572 
573  fake_select_lex->table_list.clear();
574  if (!saved_error)
575  {
576  session->limit_found_rows = (uint64_t)table->cursor->stats.records + add_rows;
577  session->examined_row_count+= examined_rows;
578  }
579  /*
580  Mark for slow query log if any of the union parts didn't use
581  indexes efficiently
582  */
583  }
584  }
585  session->lex().current_select= lex_select_save;
586  return(saved_error);
587 }
588 
589 
590 bool Select_Lex_Unit::cleanup()
591 {
592  int error= 0;
593 
594  if (cleaned)
595  {
596  return false;
597  }
598  cleaned= 1;
599 
600  if (union_result)
601  {
602  safe_delete(union_result);
603  table= 0; // Safety
604  }
605 
606  for (Select_Lex *sl= first_select(); sl; sl= sl->next_select())
607  error|= sl->cleanup();
608 
609  if (fake_select_lex)
610  {
611  Join *join;
612  if ((join= fake_select_lex->join))
613  {
614  join->tables_list= 0;
615  join->tables= 0;
616  }
617  error|= fake_select_lex->cleanup();
618  if (fake_select_lex->order_list.size())
619  {
620  Order *ord;
621  for (ord= (Order*)fake_select_lex->order_list.first; ord; ord= ord->next)
622  (*ord->item)->cleanup();
623  }
624  }
625 
626  return(error);
627 }
628 
629 
630 void Select_Lex_Unit::reinit_exec_mechanism()
631 {
632  prepared= optimized= executed= 0;
633 }
634 
635 
636 /*
637  change select_result object of unit
638 
639  SYNOPSIS
640  Select_Lex_Unit::change_result()
641  result new select_result object
642  old_result old select_result object
643 
644  RETURN
645  false - OK
646  true - error
647 */
648 
649 bool Select_Lex_Unit::change_result(select_result_interceptor *new_result,
650  select_result_interceptor *old_result)
651 {
652  bool res= false;
653  for (Select_Lex *sl= first_select(); sl; sl= sl->next_select())
654  {
655  if (sl->join && sl->join->result == old_result)
656  if (sl->join->change_result(new_result))
657  return true;
658  }
659  if (fake_select_lex && fake_select_lex->join)
660  res= fake_select_lex->join->change_result(new_result);
661  return (res);
662 }
663 
664 /*
665  Get column type information for this unit.
666 
667  SYNOPSIS
668  Select_Lex_Unit::get_unit_column_types()
669 
670  DESCRIPTION
671  For a single-select the column types are taken
672  from the list of selected items. For a union this function
673  assumes that Select_Lex_Unit::prepare has been called
674  and returns the type holders that were created for unioned
675  column types of all selects.
676 
677  NOTES
678  The implementation of this function should be in sync with
679  Select_Lex_Unit::prepare()
680 */
681 
682 List<Item> *Select_Lex_Unit::get_unit_column_types()
683 {
684  Select_Lex *sl= first_select();
685 
686  if (is_union())
687  {
688  assert(prepared);
689  /* Types are generated during prepare */
690  return &types;
691  }
692 
693  return &sl->item_list;
694 }
695 
696 bool Select_Lex::cleanup()
697 {
698  bool error= false;
699 
700  if (join)
701  {
702  assert((Select_Lex*)join->select_lex == this);
703  error= join->destroy();
704  safe_delete(join);
705  }
706  for (Select_Lex_Unit *lex_unit= first_inner_unit(); lex_unit ;
707  lex_unit= lex_unit->next_unit())
708  {
709  error= (bool) ((uint32_t) error | (uint32_t) lex_unit->cleanup());
710  }
711  non_agg_fields.clear();
712  inner_refs_list.clear();
713  return(error);
714 }
715 
716 
717 void Select_Lex::cleanup_all_joins(bool full)
718 {
719  Select_Lex_Unit *unit;
720  Select_Lex *sl;
721 
722  if (join)
723  join->cleanup(full);
724 
725  for (unit= first_inner_unit(); unit; unit= unit->next_unit())
726  for (sl= unit->first_select(); sl; sl= sl->next_select())
727  sl->cleanup_all_joins(full);
728 }
729 
730 } /* namespace drizzled */
Table * create_tmp_table(Session *session, Tmp_Table_Param *param, List< Item > &fields, Order *group, bool distinct, bool save_sum_fields, uint64_t select_options, ha_rows rows_limit, const char *alias)
Definition: table.cc:717
TODO: Rename this file - func.h is stupid.
int ha_delete_all_rows()
Definition: cursor.cc:636
bool select_query(Session *session, Item ***rref_pointer_array, TableList *tables, uint32_t wild_num, List< Item > &fields, COND *conds, uint32_t og_num, Order *order, Order *group, Item *having, uint64_t select_options, select_result *result, Select_Lex_Unit *unit, Select_Lex *select_lex)
Definition: sql_select.cc:368
Cursor * cursor
Definition: table.h:68
virtual bool is_fatal_error(int error, uint32_t flags)
Definition: cursor.cc:190