Drizzled Public API Documentation

sql_union.cc
00001 /* Copyright (C) 2000-2003 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
00015 
00016 /*
00017   UNION  of select's
00018   UNION's  were introduced by Monty and Sinisa <sinisa@mysql.com>
00019 */
00020 #include <config.h>
00021 
00022 #include <drizzled/sql_select.h>
00023 #include <drizzled/error.h>
00024 #include <drizzled/item/type_holder.h>
00025 #include <drizzled/sql_base.h>
00026 #include <drizzled/sql_union.h>
00027 #include <drizzled/select_union.h>
00028 #include <drizzled/sql_lex.h>
00029 #include <drizzled/session.h>
00030 #include <drizzled/item/subselect.h>
00031 
00032 namespace drizzled {
00033 
00034 bool drizzle_union(Session *session, LEX *, select_result *result,
00035        Select_Lex_Unit *unit, uint64_t setup_tables_done_option)
00036 {
00037   bool res= unit->prepare(session, result, SELECT_NO_UNLOCK | setup_tables_done_option);
00038   if (not res)
00039     res= unit->exec();
00040   if (res)
00041     unit->cleanup();
00042   return res;
00043 }
00044 
00045 
00046 /***************************************************************************
00047 ** store records in temporary table for UNION
00048 ***************************************************************************/
00049 
00050 int select_union::prepare(List<Item> &, Select_Lex_Unit *u)
00051 {
00052   unit= u;
00053   return 0;
00054 }
00055 
00056 
00057 bool select_union::send_data(List<Item> &values)
00058 {
00059   int error= 0;
00060   if (unit->offset_limit_cnt)
00061   {           // using limit offset,count
00062     unit->offset_limit_cnt--;
00063     return 0;
00064   }
00065   fill_record(session, table->getFields(), values, true);
00066   if (session->is_error())
00067     return 1;
00068 
00069   if ((error= table->cursor->insertRecord(table->getInsertRecord())))
00070   {
00071     /* create_myisam_from_heap will generate error if needed */
00072     if (table->cursor->is_fatal_error(error, HA_CHECK_DUP))
00073     {
00074       my_error(ER_USE_SQL_BIG_RESULT, MYF(0));
00075       return true;
00076     }
00077   }
00078   return 0;
00079 }
00080 
00081 
00082 bool select_union::send_eof()
00083 {
00084   return 0;
00085 }
00086 
00087 
00088 bool select_union::flush()
00089 {
00090   int error;
00091   if ((error=table->cursor->extra(HA_EXTRA_NO_CACHE)))
00092   {
00093     table->print_error(error, MYF(0));
00094     return 1;
00095   }
00096   return 0;
00097 }
00098 
00099 /*
00100   Create a temporary table to store the result of select_union.
00101 
00102   SYNOPSIS
00103     select_union::create_result_table()
00104       session                thread handle
00105       column_types       a list of items used to define columns of the
00106                          temporary table
00107       is_union_distinct  if set, the temporary table will eliminate
00108                          duplicates on insert
00109       options            create options
00110       table_alias        name of the temporary table
00111 
00112   DESCRIPTION
00113     Create a temporary table that is used to store the result of a UNION,
00114     derived table, or a materialized cursor.
00115 
00116   RETURN VALUE
00117     0                    The table has been created successfully.
00118     1                    create_tmp_table failed.
00119 */
00120 
00121 bool
00122 select_union::create_result_table(Session *session_arg, List<Item> *column_types,
00123                                   bool is_union_distinct, uint64_t options,
00124                                   const char *table_alias)
00125 {
00126   assert(table == NULL);
00127   tmp_table_param.init();
00128   tmp_table_param.field_count= column_types->size();
00129 
00130   if (! (table= create_tmp_table(session_arg, &tmp_table_param, *column_types,
00131                                  (Order*) NULL, is_union_distinct, 1,
00132                                  options, HA_POS_ERROR, (char*) table_alias)))
00133   {
00134     return true;
00135   }
00136 
00137   table->cursor->extra(HA_EXTRA_WRITE_CACHE);
00138   table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
00139 
00140   return false;
00141 }
00142 
00143 
00151 void select_union::cleanup()
00152 {
00153   table->cursor->extra(HA_EXTRA_RESET_STATE);
00154   table->cursor->ha_delete_all_rows();
00155   table->free_io_cache();
00156   table->filesort_free_buffers();
00157 }
00158 
00159 
00160 /*
00161   initialization procedures before fake_select_lex preparation()
00162 
00163   SYNOPSIS
00164     Select_Lex_Unit::init_prepare_fake_select_lex()
00165     session   - thread handler
00166 
00167   RETURN
00168     options of SELECT
00169 */
00170 
00171 void
00172 Select_Lex_Unit::init_prepare_fake_select_lex(Session *session_arg)
00173 {
00174   session_arg->lex().current_select= fake_select_lex;
00175   fake_select_lex->table_list.link_in_list((unsigned char *)&result_table_list,
00176              (unsigned char **)
00177              &result_table_list.next_local);
00178   fake_select_lex->context.table_list=
00179     fake_select_lex->context.first_name_resolution_table=
00180     fake_select_lex->get_table_list();
00181 
00182   for (Order *order= (Order *) global_parameters->order_list.first;
00183        order;
00184        order= order->next)
00185     order->item= &order->item_ptr;
00186 
00187   for (Order *order= (Order *)global_parameters->order_list.first;
00188        order;
00189        order=order->next)
00190   {
00191     (*order->item)->walk(&Item::change_context_processor, 0,
00192                          (unsigned char*) &fake_select_lex->context);
00193   }
00194 }
00195 
00196 
00197 bool Select_Lex_Unit::prepare(Session *session_arg, select_result *sel_result,
00198                               uint64_t additional_options)
00199 {
00200   Select_Lex *lex_select_save= session_arg->lex().current_select;
00201   Select_Lex *sl, *first_sl= first_select();
00202   select_result *tmp_result;
00203   bool is_union_select;
00204   Table *empty_table= 0;
00205 
00206   describe= test(additional_options & SELECT_DESCRIBE);
00207 
00208   /*
00209     result object should be reassigned even if preparing already done for
00210     max/min subquery (ALL/ANY optimization)
00211   */
00212   result= sel_result;
00213 
00214   if (prepared)
00215   {
00216     if (describe)
00217     {
00218       /* fast reinit for EXPLAIN */
00219       for (sl= first_sl; sl; sl= sl->next_select())
00220       {
00221   sl->join->result= result;
00222   select_limit_cnt= HA_POS_ERROR;
00223   offset_limit_cnt= 0;
00224   if (result->prepare(sl->join->fields_list, this))
00225   {
00226     return true;
00227   }
00228   sl->join->select_options|= SELECT_DESCRIBE;
00229   sl->join->reinit();
00230       }
00231     }
00232     return false;
00233   }
00234   prepared= 1;
00235   saved_error= false;
00236 
00237   session_arg->lex().current_select= sl= first_sl;
00238   found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
00239   is_union_select= is_union() || fake_select_lex;
00240 
00241   /* Global option */
00242 
00243   if (is_union_select)
00244   {
00245     tmp_result= union_result= new select_union;
00246     if (describe)
00247       tmp_result= sel_result;
00248   }
00249   else
00250     tmp_result= sel_result;
00251 
00252   sl->context.resolve_in_select_list= true;
00253 
00254   for (;sl; sl= sl->next_select())
00255   {
00256     bool can_skip_order_by;
00257     sl->options|=  SELECT_NO_UNLOCK;
00258     Join *join= new Join(session_arg, sl->item_list,
00259        sl->options | session_arg->options | additional_options,
00260        tmp_result);
00261     /*
00262       setup_tables_done_option should be set only for very first SELECT,
00263       because it protect from secont setup_tables call for select-like non
00264       select commands (DELETE/INSERT/...) and they use only very first
00265       SELECT (for union it can be only INSERT ... SELECT).
00266     */
00267     additional_options&= ~OPTION_SETUP_TABLES_DONE;
00268     if (!join)
00269       goto err;
00270 
00271     session_arg->lex().current_select= sl;
00272 
00273     can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit);
00274 
00275     saved_error= join->prepare(&sl->ref_pointer_array,
00276                                (TableList*) sl->table_list.first,
00277                                sl->with_wild,
00278                                sl->where,
00279                                (can_skip_order_by ? 0 :
00280                                 sl->order_list.size()) +
00281                                sl->group_list.size(),
00282                                can_skip_order_by ?
00283                                (Order*) NULL : (Order *)sl->order_list.first,
00284                                (Order*) sl->group_list.first,
00285                                sl->having,
00286                                sl, this);
00287     /* There are no * in the statement anymore (for PS) */
00288     sl->with_wild= 0;
00289 
00290     if (saved_error || (saved_error= session_arg->is_fatal_error))
00291       goto err;
00292     /*
00293       Use items list of underlaid select for derived tables to preserve
00294       information about fields lengths and exact types
00295     */
00296     if (!is_union_select)
00297       types= first_sl->item_list;
00298     else if (sl == first_sl)
00299     {
00300       /*
00301         We need to create an empty table object. It is used
00302         to create tmp_table fields in Item_type_holder.
00303         The main reason of this is that we can't create
00304         field object without table.
00305       */
00306       assert(!empty_table);
00307       empty_table= (Table*) session->mem.calloc(sizeof(Table));
00308       types.clear();
00309       List<Item>::iterator it(sl->item_list.begin());
00310       while (Item* item_tmp= it++)
00311       {
00312   /* Error's in 'new' will be detected after loop */
00313   types.push_back(new Item_type_holder(session_arg, item_tmp));
00314       }
00315 
00316       if (session_arg->is_fatal_error)
00317   goto err; // out of memory
00318     }
00319     else
00320     {
00321       if (types.size() != sl->item_list.size())
00322       {
00323   my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
00324        ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
00325   goto err;
00326       }
00327       List<Item>::iterator it(sl->item_list.begin());
00328       List<Item>::iterator tp(types.begin());
00329       Item *type, *item_tmp;
00330       while ((type= tp++, item_tmp= it++))
00331       {
00332         if (((Item_type_holder*)type)->join_types(session_arg, item_tmp))
00333     return true;
00334       }
00335     }
00336   }
00337 
00338   if (is_union_select)
00339   {
00340     /*
00341       Check that it was possible to aggregate
00342       all collations together for UNION.
00343     */
00344     List<Item>::iterator tp(types.begin());
00345     Item *type;
00346     uint64_t create_options;
00347 
00348     while ((type= tp++))
00349     {
00350       if (type->result_type() == STRING_RESULT &&
00351           type->collation.derivation == DERIVATION_NONE)
00352       {
00353         my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), "UNION");
00354         goto err;
00355       }
00356     }
00357 
00358     create_options= first_sl->options | session_arg->options | TMP_TABLE_ALL_COLUMNS;
00359 
00360     if (union_result->create_result_table(session, &types, test(union_distinct), create_options, ""))
00361       goto err;
00362     memset(&result_table_list, 0, sizeof(result_table_list));
00363     result_table_list.setSchemaName("");
00364     result_table_list.alias= "union";
00365     result_table_list.setTableName("union");
00366     result_table_list.table= table= union_result->table;
00367 
00368     session_arg->lex().current_select= lex_select_save;
00369     if (item_list.is_empty())
00370       table->fill_item_list(item_list);
00371     else
00372     {
00373       /*
00374         We're in execution of a prepared statement or stored procedure:
00375         reset field items to point at fields from the created temporary table.
00376       */
00377       assert(false);
00378     }
00379   }
00380 
00381   session_arg->lex().current_select= lex_select_save;
00382 
00383   return(saved_error || session_arg->is_fatal_error);
00384 
00385 err:
00386   session_arg->lex().current_select= lex_select_save;
00387   return true;
00388 }
00389 
00390 
00391 bool Select_Lex_Unit::exec()
00392 {
00393   Select_Lex *lex_select_save= session->lex().current_select;
00394   Select_Lex *select_cursor=first_select();
00395   uint64_t add_rows=0;
00396   ha_rows examined_rows= 0;
00397 
00398   if (executed && uncacheable.none() && ! describe)
00399     return false;
00400   executed= 1;
00401 
00402   if (uncacheable.any() || ! item || ! item->assigned() || describe)
00403   {
00404     if (item)
00405       item->reset_value_registration();
00406     if (optimized && item)
00407     {
00408       if (item->assigned())
00409       {
00410         item->assigned(0); // We will reinit & rexecute unit
00411         item->reset();
00412         table->cursor->ha_delete_all_rows();
00413       }
00414       /* re-enabling indexes for next subselect iteration */
00415       if (union_distinct && table->cursor->ha_enable_indexes(HA_KEY_SWITCH_ALL))
00416       {
00417         assert(0);
00418       }
00419     }
00420     for (Select_Lex *sl= select_cursor; sl; sl= sl->next_select())
00421     {
00422       ha_rows records_at_start= 0;
00423       session->lex().current_select= sl;
00424 
00425       if (optimized)
00426   saved_error= sl->join->reinit();
00427       else
00428       {
00429         set_limit(sl);
00430   if (sl == global_parameters || describe)
00431   {
00432     offset_limit_cnt= 0;
00433     /*
00434       We can't use LIMIT at this stage if we are using ORDER BY for the
00435       whole query
00436     */
00437     if (sl->order_list.first || describe)
00438       select_limit_cnt= HA_POS_ERROR;
00439         }
00440 
00441         /*
00442           When using braces, SQL_CALC_FOUND_ROWS affects the whole query:
00443           we don't calculate found_rows() per union part.
00444           Otherwise, SQL_CALC_FOUND_ROWS should be done on all sub parts.
00445         */
00446         sl->join->select_options=
00447           (select_limit_cnt == HA_POS_ERROR || sl->braces) ?
00448           sl->options & ~OPTION_FOUND_ROWS : sl->options | found_rows_for_union;
00449 
00450   saved_error= sl->join->optimize();
00451       }
00452       if (!saved_error)
00453       {
00454   records_at_start= table->cursor->stats.records;
00455   sl->join->exec();
00456         if (sl == union_distinct)
00457   {
00458     if (table->cursor->ha_disable_indexes(HA_KEY_SWITCH_ALL))
00459       return true;
00460     table->no_keyread=1;
00461   }
00462   saved_error= sl->join->error;
00463   offset_limit_cnt= (ha_rows)(sl->offset_limit ?
00464                                     sl->offset_limit->val_uint() :
00465                                     0);
00466   if (!saved_error)
00467   {
00468     examined_rows+= session->examined_row_count;
00469     if (union_result->flush())
00470     {
00471       session->lex().current_select= lex_select_save;
00472       return 1;
00473     }
00474   }
00475       }
00476       if (saved_error)
00477       {
00478   session->lex().current_select= lex_select_save;
00479   return(saved_error);
00480       }
00481       /* Needed for the following test and for records_at_start in next loop */
00482       int error= table->cursor->info(HA_STATUS_VARIABLE);
00483       if (error)
00484       {
00485         table->print_error(error, MYF(0));
00486         return 1;
00487       }
00488       if (found_rows_for_union && !sl->braces &&
00489           select_limit_cnt != HA_POS_ERROR)
00490       {
00491   /*
00492     This is a union without braces. Remember the number of rows that
00493     could also have been part of the result set.
00494     We get this from the difference of between total number of possible
00495     rows and actual rows added to the temporary table.
00496   */
00497   add_rows+= (uint64_t) (session->limit_found_rows - (uint64_t)
00498             ((table->cursor->stats.records -  records_at_start)));
00499       }
00500     }
00501   }
00502   optimized= 1;
00503 
00504   /* Send result to 'result' */
00505   saved_error= true;
00506   {
00507     if (!session->is_fatal_error)       // Check if EOM
00508     {
00509       set_limit(global_parameters);
00510       init_prepare_fake_select_lex(session);
00511       Join *join= fake_select_lex->join;
00512       if (!join)
00513       {
00514   /*
00515     allocate JOIN for fake select only once (prevent
00516     select_query automatic allocation)
00517           TODO: The above is nonsense. select_query() will not allocate the
00518           join if one already exists. There must be some other reason why we
00519           don't let it allocate the join. Perhaps this is because we need
00520           some special parameter values passed to join constructor?
00521   */
00522   fake_select_lex->join= new Join(session, item_list, fake_select_lex->options, result);
00523   fake_select_lex->join->no_const_tables= true;
00524 
00525   /*
00526     Fake Select_Lex should have item list for correctref_array
00527     allocation.
00528   */
00529   fake_select_lex->item_list= item_list;
00530         saved_error= select_query(session, &fake_select_lex->ref_pointer_array,
00531                               &result_table_list,
00532                               0, item_list, NULL,
00533                               global_parameters->order_list.size(),
00534                               (Order*)global_parameters->order_list.first,
00535                               (Order*) NULL, NULL,
00536                               fake_select_lex->options | SELECT_NO_UNLOCK,
00537                               result, this, fake_select_lex);
00538       }
00539       else
00540       {
00541         if (describe)
00542         {
00543           /*
00544             In EXPLAIN command, constant subqueries that do not use any
00545             tables are executed two times:
00546              - 1st time is a real evaluation to get the subquery value
00547              - 2nd time is to produce EXPLAIN output rows.
00548             1st execution sets certain members (e.g. select_result) to perform
00549             subquery execution rather than EXPLAIN line production. In order
00550             to reset them back, we re-do all of the actions (yes it is ugly):
00551           */
00552           join->reset(session, item_list, fake_select_lex->options, result);
00553           saved_error= select_query(session, &fake_select_lex->ref_pointer_array,
00554                                 &result_table_list,
00555                                 0, item_list, NULL,
00556                                 global_parameters->order_list.size(),
00557                                 (Order*)global_parameters->order_list.first,
00558                                 (Order*) NULL, NULL,
00559                                 fake_select_lex->options | SELECT_NO_UNLOCK,
00560                                 result, this, fake_select_lex);
00561         }
00562         else
00563         {
00564           join->examined_rows= 0;
00565           saved_error= join->reinit();
00566           join->exec();
00567         }
00568       }
00569 
00570       fake_select_lex->table_list.clear();
00571       if (!saved_error)
00572       {
00573   session->limit_found_rows = (uint64_t)table->cursor->stats.records + add_rows;
00574         session->examined_row_count+= examined_rows;
00575       }
00576       /*
00577   Mark for slow query log if any of the union parts didn't use
00578   indexes efficiently
00579       */
00580     }
00581   }
00582   session->lex().current_select= lex_select_save;
00583   return(saved_error);
00584 }
00585 
00586 
00587 bool Select_Lex_Unit::cleanup()
00588 {
00589   int error= 0;
00590 
00591   if (cleaned)
00592   {
00593     return false;
00594   }
00595   cleaned= 1;
00596 
00597   if (union_result)
00598   {
00599     safe_delete(union_result);
00600     table= 0; // Safety
00601   }
00602 
00603   for (Select_Lex *sl= first_select(); sl; sl= sl->next_select())
00604     error|= sl->cleanup();
00605 
00606   if (fake_select_lex)
00607   {
00608     Join *join;
00609     if ((join= fake_select_lex->join))
00610     {
00611       join->tables_list= 0;
00612       join->tables= 0;
00613     }
00614     error|= fake_select_lex->cleanup();
00615     if (fake_select_lex->order_list.size())
00616     {
00617       Order *ord;
00618       for (ord= (Order*)fake_select_lex->order_list.first; ord; ord= ord->next)
00619         (*ord->item)->cleanup();
00620     }
00621   }
00622 
00623   return(error);
00624 }
00625 
00626 
00627 void Select_Lex_Unit::reinit_exec_mechanism()
00628 {
00629   prepared= optimized= executed= 0;
00630 }
00631 
00632 
00633 /*
00634   change select_result object of unit
00635 
00636   SYNOPSIS
00637     Select_Lex_Unit::change_result()
00638     result  new select_result object
00639     old_result  old select_result object
00640 
00641   RETURN
00642     false - OK
00643     true  - error
00644 */
00645 
00646 bool Select_Lex_Unit::change_result(select_result_interceptor *new_result,
00647                                        select_result_interceptor *old_result)
00648 {
00649   bool res= false;
00650   for (Select_Lex *sl= first_select(); sl; sl= sl->next_select())
00651   {
00652     if (sl->join && sl->join->result == old_result)
00653       if (sl->join->change_result(new_result))
00654   return true;
00655   }
00656   if (fake_select_lex && fake_select_lex->join)
00657     res= fake_select_lex->join->change_result(new_result);
00658   return (res);
00659 }
00660 
00661 /*
00662   Get column type information for this unit.
00663 
00664   SYNOPSIS
00665     Select_Lex_Unit::get_unit_column_types()
00666 
00667   DESCRIPTION
00668     For a single-select the column types are taken
00669     from the list of selected items. For a union this function
00670     assumes that Select_Lex_Unit::prepare has been called
00671     and returns the type holders that were created for unioned
00672     column types of all selects.
00673 
00674   NOTES
00675     The implementation of this function should be in sync with
00676     Select_Lex_Unit::prepare()
00677 */
00678 
00679 List<Item> *Select_Lex_Unit::get_unit_column_types()
00680 {
00681   Select_Lex *sl= first_select();
00682 
00683   if (is_union())
00684   {
00685     assert(prepared);
00686     /* Types are generated during prepare */
00687     return &types;
00688   }
00689 
00690   return &sl->item_list;
00691 }
00692 
00693 bool Select_Lex::cleanup()
00694 {
00695   bool error= false;
00696 
00697   if (join)
00698   {
00699     assert((Select_Lex*)join->select_lex == this);
00700     error= join->destroy();
00701     safe_delete(join);
00702   }
00703   for (Select_Lex_Unit *lex_unit= first_inner_unit(); lex_unit ;
00704        lex_unit= lex_unit->next_unit())
00705   {
00706     error= (bool) ((uint32_t) error | (uint32_t) lex_unit->cleanup());
00707   }
00708   non_agg_fields.clear();
00709   inner_refs_list.clear();
00710   return(error);
00711 }
00712 
00713 
00714 void Select_Lex::cleanup_all_joins(bool full)
00715 {
00716   Select_Lex_Unit *unit;
00717   Select_Lex *sl;
00718 
00719   if (join)
00720     join->cleanup(full);
00721 
00722   for (unit= first_inner_unit(); unit; unit= unit->next_unit())
00723     for (sl= unit->first_select(); sl; sl= sl->next_select())
00724       sl->cleanup_all_joins(full);
00725 }
00726 
00727 } /* namespace drizzled */