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  types= first_sl->item_list;
298  else if (sl == first_sl)
299  {
300  /*
301  We need to create an empty table object. It is used
302  to create tmp_table fields in Item_type_holder.
303  The main reason of this is that we can't create
304  field object without table.
305  */
306  assert(!empty_table);
307  empty_table= (Table*) session->mem.calloc(sizeof(Table));
308  types.clear();
309  List<Item>::iterator it(sl->item_list.begin());
310  while (Item* item_tmp= it++)
311  {
312  /* Error's in 'new' will be detected after loop */
313  types.push_back(new Item_type_holder(session_arg, item_tmp));
314  }
315 
316  if (session_arg->is_fatal_error)
317  goto err; // out of memory
318  }
319  else
320  {
321  if (types.size() != sl->item_list.size())
322  {
323  my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
324  ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
325  goto err;
326  }
327  List<Item>::iterator it(sl->item_list.begin());
328  List<Item>::iterator tp(types.begin());
329  Item *type, *item_tmp;
330  while ((type= tp++, item_tmp= it++))
331  {
332  if (((Item_type_holder*)type)->join_types(session_arg, item_tmp))
333  return true;
334  }
335  }
336  }
337 
338  if (is_union_select)
339  {
340  /*
341  Check that it was possible to aggregate
342  all collations together for UNION.
343  */
344  List<Item>::iterator tp(types.begin());
345  Item *type;
346  uint64_t create_options;
347 
348  while ((type= tp++))
349  {
350  if (type->result_type() == STRING_RESULT &&
351  type->collation.derivation == DERIVATION_NONE)
352  {
353  my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), "UNION");
354  goto err;
355  }
356  }
357 
358  create_options= first_sl->options | session_arg->options | TMP_TABLE_ALL_COLUMNS;
359 
360  if (union_result->create_result_table(session, &types, test(union_distinct), create_options, ""))
361  goto err;
362  memset(&result_table_list, 0, sizeof(result_table_list));
363  result_table_list.setSchemaName("");
364  result_table_list.alias= "union";
365  result_table_list.setTableName("union");
366  result_table_list.table= table= union_result->table;
367 
368  session_arg->lex().current_select= lex_select_save;
369  if (item_list.is_empty())
370  table->fill_item_list(item_list);
371  else
372  {
373  /*
374  We're in execution of a prepared statement or stored procedure:
375  reset field items to point at fields from the created temporary table.
376  */
377  assert(false);
378  }
379  }
380 
381  session_arg->lex().current_select= lex_select_save;
382 
383  return(saved_error || session_arg->is_fatal_error);
384 
385 err:
386  session_arg->lex().current_select= lex_select_save;
387  return true;
388 }
389 
390 
391 bool Select_Lex_Unit::exec()
392 {
393  Select_Lex *lex_select_save= session->lex().current_select;
394  Select_Lex *select_cursor=first_select();
395  uint64_t add_rows=0;
396  ha_rows examined_rows= 0;
397 
398  if (executed && uncacheable.none() && ! describe)
399  return false;
400  executed= 1;
401 
402  if (uncacheable.any() || ! item || ! item->assigned() || describe)
403  {
404  if (item)
405  item->reset_value_registration();
406  if (optimized && item)
407  {
408  if (item->assigned())
409  {
410  item->assigned(0); // We will reinit & rexecute unit
411  item->reset();
412  table->cursor->ha_delete_all_rows();
413  }
414  /* re-enabling indexes for next subselect iteration */
415  if (union_distinct && table->cursor->ha_enable_indexes(HA_KEY_SWITCH_ALL))
416  {
417  assert(0);
418  }
419  }
420  for (Select_Lex *sl= select_cursor; sl; sl= sl->next_select())
421  {
422  ha_rows records_at_start= 0;
423  session->lex().current_select= sl;
424 
425  if (optimized)
426  saved_error= sl->join->reinit();
427  else
428  {
429  set_limit(sl);
430  if (sl == global_parameters || describe)
431  {
432  offset_limit_cnt= 0;
433  /*
434  We can't use LIMIT at this stage if we are using ORDER BY for the
435  whole query
436  */
437  if (sl->order_list.first || describe)
438  select_limit_cnt= HA_POS_ERROR;
439  }
440 
441  /*
442  When using braces, SQL_CALC_FOUND_ROWS affects the whole query:
443  we don't calculate found_rows() per union part.
444  Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
445  */
446  sl->join->select_options=
447  (select_limit_cnt == HA_POS_ERROR || sl->braces) ?
448  sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
449 
450  saved_error= sl->join->optimize();
451  }
452  if (!saved_error)
453  {
454  records_at_start= table->cursor->stats.records;
455  sl->join->exec();
456  if (sl == union_distinct)
457  {
458  if (table->cursor->ha_disable_indexes(HA_KEY_SWITCH_ALL))
459  return true;
460  table->no_keyread=1;
461  }
462  saved_error= sl->join->error;
463  offset_limit_cnt= (ha_rows)(sl->offset_limit ?
464  sl->offset_limit->val_uint() :
465  0);
466  if (!saved_error)
467  {
468  examined_rows+= session->examined_row_count;
469  if (union_result->flush())
470  {
471  session->lex().current_select= lex_select_save;
472  return 1;
473  }
474  }
475  }
476  if (saved_error)
477  {
478  session->lex().current_select= lex_select_save;
479  return(saved_error);
480  }
481  /* Needed for the following test and for records_at_start in next loop */
482  int error= table->cursor->info(HA_STATUS_VARIABLE);
483  if (error)
484  {
485  table->print_error(error, MYF(0));
486  return 1;
487  }
488  if (found_rows_for_union && !sl->braces &&
489  select_limit_cnt != HA_POS_ERROR)
490  {
491  /*
492  This is a union without braces. Remember the number of rows that
493  could also have been part of the result set.
494  We get this from the difference of between total number of possible
495  rows and actual rows added to the temporary table.
496  */
497  add_rows+= (uint64_t) (session->limit_found_rows - (uint64_t)
498  ((table->cursor->stats.records - records_at_start)));
499  }
500  }
501  }
502  optimized= 1;
503 
504  /* Send result to 'result' */
505  saved_error= true;
506  {
507  if (!session->is_fatal_error) // Check if EOM
508  {
509  set_limit(global_parameters);
510  init_prepare_fake_select_lex(session);
511  Join *join= fake_select_lex->join;
512  if (!join)
513  {
514  /*
515  allocate JOIN for fake select only once (prevent
516  select_query automatic allocation)
517  TODO: The above is nonsense. select_query() will not allocate the
518  join if one already exists. There must be some other reason why we
519  don't let it allocate the join. Perhaps this is because we need
520  some special parameter values passed to join constructor?
521  */
522  fake_select_lex->join= new Join(session, item_list, fake_select_lex->options, result);
523  fake_select_lex->join->no_const_tables= true;
524 
525  /*
526  Fake Select_Lex should have item list for correctref_array
527  allocation.
528  */
529  fake_select_lex->item_list= item_list;
530  saved_error= select_query(session, &fake_select_lex->ref_pointer_array,
531  &result_table_list,
532  0, item_list, NULL,
533  global_parameters->order_list.size(),
534  (Order*)global_parameters->order_list.first,
535  (Order*) NULL, NULL,
536  fake_select_lex->options | SELECT_NO_UNLOCK,
537  result, this, fake_select_lex);
538  }
539  else
540  {
541  if (describe)
542  {
543  /*
544  In EXPLAIN command, constant subqueries that do not use any
545  tables are executed two times:
546  - 1st time is a real evaluation to get the subquery value
547  - 2nd time is to produce EXPLAIN output rows.
548  1st execution sets certain members (e.g. select_result) to perform
549  subquery execution rather than EXPLAIN line production. In order
550  to reset them back, we re-do all of the actions (yes it is ugly):
551  */
552  join->reset(session, item_list, fake_select_lex->options, result);
553  saved_error= select_query(session, &fake_select_lex->ref_pointer_array,
554  &result_table_list,
555  0, item_list, NULL,
556  global_parameters->order_list.size(),
557  (Order*)global_parameters->order_list.first,
558  (Order*) NULL, NULL,
559  fake_select_lex->options | SELECT_NO_UNLOCK,
560  result, this, fake_select_lex);
561  }
562  else
563  {
564  join->examined_rows= 0;
565  saved_error= join->reinit();
566  join->exec();
567  }
568  }
569 
570  fake_select_lex->table_list.clear();
571  if (!saved_error)
572  {
573  session->limit_found_rows = (uint64_t)table->cursor->stats.records + add_rows;
574  session->examined_row_count+= examined_rows;
575  }
576  /*
577  Mark for slow query log if any of the union parts didn't use
578  indexes efficiently
579  */
580  }
581  }
582  session->lex().current_select= lex_select_save;
583  return(saved_error);
584 }
585 
586 
587 bool Select_Lex_Unit::cleanup()
588 {
589  int error= 0;
590 
591  if (cleaned)
592  {
593  return false;
594  }
595  cleaned= 1;
596 
597  if (union_result)
598  {
599  safe_delete(union_result);
600  table= 0; // Safety
601  }
602 
603  for (Select_Lex *sl= first_select(); sl; sl= sl->next_select())
604  error|= sl->cleanup();
605 
606  if (fake_select_lex)
607  {
608  Join *join;
609  if ((join= fake_select_lex->join))
610  {
611  join->tables_list= 0;
612  join->tables= 0;
613  }
614  error|= fake_select_lex->cleanup();
615  if (fake_select_lex->order_list.size())
616  {
617  Order *ord;
618  for (ord= (Order*)fake_select_lex->order_list.first; ord; ord= ord->next)
619  (*ord->item)->cleanup();
620  }
621  }
622 
623  return(error);
624 }
625 
626 
627 void Select_Lex_Unit::reinit_exec_mechanism()
628 {
629  prepared= optimized= executed= 0;
630 }
631 
632 
633 /*
634  change select_result object of unit
635 
636  SYNOPSIS
637  Select_Lex_Unit::change_result()
638  result new select_result object
639  old_result old select_result object
640 
641  RETURN
642  false - OK
643  true - error
644 */
645 
646 bool Select_Lex_Unit::change_result(select_result_interceptor *new_result,
647  select_result_interceptor *old_result)
648 {
649  bool res= false;
650  for (Select_Lex *sl= first_select(); sl; sl= sl->next_select())
651  {
652  if (sl->join && sl->join->result == old_result)
653  if (sl->join->change_result(new_result))
654  return true;
655  }
656  if (fake_select_lex && fake_select_lex->join)
657  res= fake_select_lex->join->change_result(new_result);
658  return (res);
659 }
660 
661 /*
662  Get column type information for this unit.
663 
664  SYNOPSIS
665  Select_Lex_Unit::get_unit_column_types()
666 
667  DESCRIPTION
668  For a single-select the column types are taken
669  from the list of selected items. For a union this function
670  assumes that Select_Lex_Unit::prepare has been called
671  and returns the type holders that were created for unioned
672  column types of all selects.
673 
674  NOTES
675  The implementation of this function should be in sync with
676  Select_Lex_Unit::prepare()
677 */
678 
679 List<Item> *Select_Lex_Unit::get_unit_column_types()
680 {
681  Select_Lex *sl= first_select();
682 
683  if (is_union())
684  {
685  assert(prepared);
686  /* Types are generated during prepare */
687  return &types;
688  }
689 
690  return &sl->item_list;
691 }
692 
693 bool Select_Lex::cleanup()
694 {
695  bool error= false;
696 
697  if (join)
698  {
699  assert((Select_Lex*)join->select_lex == this);
700  error= join->destroy();
701  safe_delete(join);
702  }
703  for (Select_Lex_Unit *lex_unit= first_inner_unit(); lex_unit ;
704  lex_unit= lex_unit->next_unit())
705  {
706  error= (bool) ((uint32_t) error | (uint32_t) lex_unit->cleanup());
707  }
708  non_agg_fields.clear();
709  inner_refs_list.clear();
710  return(error);
711 }
712 
713 
714 void Select_Lex::cleanup_all_joins(bool full)
715 {
716  Select_Lex_Unit *unit;
717  Select_Lex *sl;
718 
719  if (join)
720  join->cleanup(full);
721 
722  for (unit= first_inner_unit(); unit; unit= unit->next_unit())
723  for (sl= unit->first_select(); sl; sl= sl->next_select())
724  sl->cleanup_all_joins(full);
725 }
726 
727 } /* 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
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