Drizzled Public API Documentation

sql_update.cc
00001 /* Copyright (C) 2000-2006 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 /*
00018   Single table and multi table updates of tables.
00019 */
00020 
00021 #include <config.h>
00022 
00023 #include <drizzled/sql_select.h>
00024 #include <drizzled/error.h>
00025 #include <drizzled/probes.h>
00026 #include <drizzled/sql_base.h>
00027 #include <drizzled/field/epoch.h>
00028 #include <drizzled/sql_parse.h>
00029 #include <drizzled/optimizer/range.h>
00030 #include <drizzled/records.h>
00031 #include <drizzled/internal/my_sys.h>
00032 #include <drizzled/internal/iocache.h>
00033 #include <drizzled/transaction_services.h>
00034 #include <drizzled/filesort.h>
00035 #include <drizzled/plugin/storage_engine.h>
00036 #include <drizzled/key.h>
00037 #include <drizzled/sql_lex.h>
00038 #include <drizzled/diagnostics_area.h>
00039 #include <drizzled/util/test.h>
00040 #include <drizzled/statistics_variables.h>
00041 #include <drizzled/session/transactions.h>
00042 
00043 #include <boost/dynamic_bitset.hpp>
00044 #include <list>
00045 
00046 using namespace std;
00047 
00048 namespace drizzled {
00049 
00062 static void prepare_record_for_error_message(int error, Table *table)
00063 {
00064   Field **field_p= NULL;
00065   Field *field= NULL;
00066   uint32_t keynr= 0;
00067 
00068   /*
00069     Only duplicate key errors print the key value.
00070     If storage engine does always read all columns, we have the value alraedy.
00071   */
00072   if ((error != HA_ERR_FOUND_DUPP_KEY) ||
00073       ! (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ)))
00074     return;
00075 
00076   /*
00077     Get the number of the offended index.
00078     We will see MAX_KEY if the engine cannot determine the affected index.
00079   */
00080   if ((keynr= table->get_dup_key(error)) >= MAX_KEY)
00081     return;
00082 
00083   /* Create unique_map with all fields used by that index. */
00084   boost::dynamic_bitset<> unique_map(table->getShare()->sizeFields()); /* Fields in offended unique. */
00085   table->mark_columns_used_by_index_no_reset(keynr, unique_map);
00086 
00087   /* Subtract read_set and write_set. */
00088   unique_map-= *table->read_set;
00089   unique_map-= *table->write_set;
00090 
00091   /*
00092     If the unique index uses columns that are neither in read_set
00093     nor in write_set, we must re-read the record.
00094     Otherwise no need to do anything.
00095   */
00096   if (unique_map.none())
00097     return;
00098 
00099   /* Get identifier of last read record into table->cursor->ref. */
00100   table->cursor->position(table->getInsertRecord());
00101   /* Add all fields used by unique index to read_set. */
00102   *table->read_set|= unique_map;
00103   /* Read record that is identified by table->cursor->ref. */
00104   (void) table->cursor->rnd_pos(table->getUpdateRecord(), table->cursor->ref);
00105   /* Copy the newly read columns into the new record. */
00106   for (field_p= table->getFields(); (field= *field_p); field_p++)
00107   {
00108     if (unique_map.test(field->position()))
00109     {
00110       field->copy_from_tmp(table->getShare()->rec_buff_length);
00111     }
00112   }
00113 
00114   return;
00115 }
00116 
00117 
00118 /*
00119   Process usual UPDATE
00120 
00121   SYNOPSIS
00122     update_query()
00123     session     thread handler
00124     fields    fields for update
00125     values    values of fields for update
00126     conds   WHERE clause expression
00127     order_num   number of elemen in ORDER BY clause
00128     order   order_st BY clause list
00129     limit   limit clause
00130     handle_duplicates how to handle duplicates
00131 
00132   RETURN
00133     0  - OK
00134     1  - error
00135 */
00136 
00137 int update_query(Session *session, TableList *table_list,
00138                  List<Item> &fields, List<Item> &values, COND *conds,
00139                  uint32_t order_num, Order *order,
00140                  ha_rows limit, enum enum_duplicates,
00141                  bool ignore)
00142 {
00143   bool    using_limit= limit != HA_POS_ERROR;
00144   bool    used_key_is_modified;
00145   bool    transactional_table;
00146   int   error= 0;
00147   uint    used_index= MAX_KEY, dup_key_found;
00148   bool          need_sort= true;
00149   ha_rows updated, found;
00150   key_map old_covering_keys;
00151   Table   *table;
00152   optimizer::SqlSelect *select= NULL;
00153   ReadRecord  info;
00154   Select_Lex    *select_lex= &session->lex().select_lex;
00155   uint64_t     id;
00156   List<Item> all_fields;
00157   Session::killed_state_t killed_status= Session::NOT_KILLED;
00158 
00159   DRIZZLE_UPDATE_START(session->getQueryString()->c_str());
00160   if (session->openTablesLock(table_list))
00161   {
00162     DRIZZLE_UPDATE_DONE(1, 0, 0);
00163     return 1;
00164   }
00165 
00166   session->set_proc_info("init");
00167   table= table_list->table;
00168 
00169   /* Calculate "table->covering_keys" based on the WHERE */
00170   table->covering_keys= table->getShare()->keys_in_use;
00171   table->quick_keys.reset();
00172 
00173   if (prepare_update(session, table_list, &conds, order_num, order))
00174   {
00175     DRIZZLE_UPDATE_DONE(1, 0, 0);
00176     return 1;
00177   }
00178 
00179   old_covering_keys= table->covering_keys;    // Keys used in WHERE
00180   /* Check the fields we are going to modify */
00181   if (setup_fields_with_no_wrap(session, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
00182   {
00183     DRIZZLE_UPDATE_DONE(1, 0, 0);
00184     return 1;
00185   }
00186 
00187   if (table->timestamp_field)
00188   {
00189     // Don't set timestamp column if this is modified
00190     if (table->timestamp_field->isWriteSet())
00191     {
00192       table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
00193     }
00194     else
00195     {
00196       if (table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
00197           table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH)
00198       {
00199         table->setWriteSet(table->timestamp_field->position());
00200       }
00201     }
00202   }
00203 
00204   if (setup_fields(session, 0, values, MARK_COLUMNS_READ, 0, 0))
00205   {
00206     free_underlaid_joins(session, select_lex);
00207     DRIZZLE_UPDATE_DONE(1, 0, 0);
00208 
00209     return 1;
00210   }
00211 
00212   if (select_lex->inner_refs_list.size() &&
00213     fix_inner_refs(session, all_fields, select_lex, select_lex->ref_pointer_array))
00214   {
00215     DRIZZLE_UPDATE_DONE(1, 0, 0);
00216     return 1;
00217   }
00218 
00219   if (conds)
00220   {
00221     Item::cond_result cond_value;
00222     conds= remove_eq_conds(session, conds, &cond_value);
00223     if (cond_value == Item::COND_FALSE)
00224       limit= 0;                                   // Impossible WHERE
00225   }
00226 
00227   /*
00228     If a timestamp field settable on UPDATE is present then to avoid wrong
00229     update force the table handler to retrieve write-only fields to be able
00230     to compare records and detect data change.
00231   */
00232   if (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ) &&
00233       table->timestamp_field &&
00234       (table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
00235        table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
00236   {
00237     *table->read_set|= *table->write_set;
00238   }
00239   // Don't count on usage of 'only index' when calculating which key to use
00240   table->covering_keys.reset();
00241 
00242   /* Update the table->cursor->stats.records number */
00243   table->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
00244 
00245   select= optimizer::make_select(table, 0, 0, conds, 0, &error);
00246   if (error || !limit ||
00247       (select && select->check_quick(session, false, limit)))
00248   {
00249     delete select;
00254     session->main_da().reset_diagnostics_area();
00255     free_underlaid_joins(session, select_lex);
00256     if (error || session->is_error())
00257     {
00258       DRIZZLE_UPDATE_DONE(1, 0, 0);
00259       return 1;
00260     }
00261     DRIZZLE_UPDATE_DONE(0, 0, 0);
00262     session->my_ok();       // No matching records
00263     return 0;
00264   }
00265   if (!select && limit != HA_POS_ERROR)
00266   {
00267     if ((used_index= optimizer::get_index_for_order(table, order, limit)) != MAX_KEY)
00268       need_sort= false;
00269   }
00270   /* If running in safe sql mode, don't allow updates without keys */
00271   if (table->quick_keys.none())
00272   {
00273     session->server_status|=SERVER_QUERY_NO_INDEX_USED;
00274   }
00275 
00276   table->mark_columns_needed_for_update();
00277 
00278   /* Check if we are modifying a key that we are used to search with */
00279 
00280   if (select && select->quick)
00281   {
00282     used_index= select->quick->index;
00283     used_key_is_modified= (!select->quick->unique_key_range() &&
00284                           select->quick->is_keys_used(*table->write_set));
00285   }
00286   else
00287   {
00288     used_key_is_modified= 0;
00289     if (used_index == MAX_KEY)                  // no index for sort order
00290       used_index= table->cursor->key_used_on_scan;
00291     if (used_index != MAX_KEY)
00292       used_key_is_modified= is_key_used(table, used_index, *table->write_set);
00293   }
00294 
00295 
00296   if (used_key_is_modified || order)
00297   {
00298     /*
00299       We can't update table directly;  We must first search after all
00300       matching rows before updating the table!
00301     */
00302     if (used_index < MAX_KEY && old_covering_keys.test(used_index))
00303     {
00304       table->key_read=1;
00305       table->mark_columns_used_by_index(used_index);
00306     }
00307     else
00308     {
00309       table->use_all_columns();
00310     }
00311 
00312     /* note: We avoid sorting avoid if we sort on the used index */
00313     if (order && (need_sort || used_key_is_modified))
00314     {
00315       /*
00316   Doing an order_st BY;  Let filesort find and sort the rows we are going
00317   to update
00318         NOTE: filesort will call table->prepare_for_position()
00319       */
00320       uint32_t         length= 0;
00321       SortField  *sortorder;
00322       ha_rows examined_rows;
00323       FileSort filesort(*session);
00324 
00325       table->sort.io_cache= new internal::io_cache_st;
00326       sortorder=make_unireg_sortorder(order, &length, NULL);
00327 
00328       if ((table->sort.found_records= filesort.run(table, sortorder, length, select, limit, 1, examined_rows)) == HA_POS_ERROR)
00329         goto err;
00330       /*
00331   Filesort has already found and selected the rows we want to update,
00332   so we don't need the where clause
00333       */
00334       safe_delete(select);
00335     }
00336     else
00337     {
00338       /*
00339   We are doing a search on a key that is updated. In this case
00340   we go trough the matching rows, save a pointer to them and
00341   update these in a separate loop based on the pointer.
00342       */
00343 
00344       internal::io_cache_st tempfile;
00345       if (tempfile.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
00346       {
00347   goto err;
00348       }
00349 
00350       /* If quick select is used, initialize it before retrieving rows. */
00351       if (select && select->quick && select->quick->reset())
00352         goto err;
00353       table->cursor->try_semi_consistent_read(1);
00354 
00355       /*
00356         When we get here, we have one of the following options:
00357         A. used_index == MAX_KEY
00358            This means we should use full table scan, and start it with
00359            init_read_record call
00360         B. used_index != MAX_KEY
00361            B.1 quick select is used, start the scan with init_read_record
00362            B.2 quick select is not used, this is full index scan (with LIMIT)
00363                Full index scan must be started with init_read_record_idx
00364       */
00365 
00366       if (used_index == MAX_KEY || (select && select->quick))
00367       {
00368         if ((error= info.init_read_record(session, table, select, 0, true)))
00369           goto err;
00370       }
00371       else
00372       {
00373         if ((error= info.init_read_record_idx(session, table, 1, used_index)))
00374           goto err;
00375       }
00376 
00377       session->set_proc_info("Searching rows for update");
00378       ha_rows tmp_limit= limit;
00379 
00380       while (not(error= info.read_record(&info)) && not session->getKilled())
00381       {
00382   if (!(select && select->skip_record()))
00383   {
00384           if (table->cursor->was_semi_consistent_read())
00385       continue;  /* repeat the read of the same row if it still exists */
00386 
00387     table->cursor->position(table->getInsertRecord());
00388     if (tempfile.write(table->cursor->ref, table->cursor->ref_length))
00389     {
00390       error=1;
00391       break;
00392     }
00393     if (!--limit && using_limit)
00394     {
00395       error= -1;
00396       break;
00397     }
00398   }
00399   else
00400     table->cursor->unlock_row();
00401       }
00402       if (session->getKilled() && not error)
00403   error= 1;       // Aborted
00404       limit= tmp_limit;
00405       table->cursor->try_semi_consistent_read(0);
00406       info.end_read_record();
00407 
00408       /* Change select to use tempfile */
00409       if (select)
00410       {
00411   safe_delete(select->quick);
00412   if (select->free_cond)
00413     delete select->cond;
00414   select->cond=0;
00415       }
00416       else
00417       {
00418   select= new optimizer::SqlSelect();
00419   select->head=table;
00420       }
00421       if (tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
00422   error=1;
00423       // Read row ptrs from this cursor
00424       memcpy(select->file, &tempfile, sizeof(tempfile));
00425       if (error >= 0)
00426   goto err;
00427     }
00428     if (table->key_read)
00429       table->restore_column_maps_after_mark_index();
00430   }
00431 
00432   if (ignore)
00433     table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
00434 
00435   if (select && select->quick && select->quick->reset())
00436     goto err;
00437   table->cursor->try_semi_consistent_read(1);
00438   if ((error= info.init_read_record(session, table, select, 0, true)))
00439   {
00440     goto err;
00441   }
00442 
00443   updated= found= 0;
00444   /*
00445    * Per the SQL standard, inserting NULL into a NOT NULL
00446    * field requires an error to be thrown.
00447    *
00448    * @NOTE
00449    *
00450    * NULL check and handling occurs in field_conv.cc
00451    */
00452   session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
00453   session->cuted_fields= 0L;
00454   session->set_proc_info("Updating");
00455 
00456   transactional_table= table->cursor->has_transactions();
00457   session->setAbortOnWarning(test(!ignore));
00458 
00459   /*
00460     Assure that we can use position()
00461     if we need to create an error message.
00462   */
00463   if (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ))
00464     table->prepare_for_position();
00465 
00466   while (not (error=info.read_record(&info)) && not session->getKilled())
00467   {
00468     if (not (select && select->skip_record()))
00469     {
00470       if (table->cursor->was_semi_consistent_read())
00471         continue;  /* repeat the read of the same row if it still exists */
00472 
00473       table->storeRecord();
00474       if (fill_record(session, fields, values))
00475         break;
00476 
00477       found++;
00478 
00479       if (! table->records_are_comparable() || table->compare_records())
00480       {
00481         /* Non-batched update */
00482         error= table->cursor->updateRecord(table->getUpdateRecord(),
00483                                             table->getInsertRecord());
00484 
00485         table->auto_increment_field_not_null= false;
00486 
00487         if (!error || error == HA_ERR_RECORD_IS_THE_SAME)
00488         {
00489           if (error != HA_ERR_RECORD_IS_THE_SAME)
00490             updated++;
00491           else
00492             error= 0;
00493         }
00494         else if (! ignore ||
00495                  table->cursor->is_fatal_error(error, HA_CHECK_DUP_KEY))
00496         {
00497           /*
00498             If (ignore && error is ignorable) we don't have to
00499             do anything; otherwise...
00500           */
00501           myf flags= 0;
00502 
00503           if (table->cursor->is_fatal_error(error, HA_CHECK_DUP_KEY))
00504             flags|= ME_FATALERROR; /* Other handler errors are fatal */
00505 
00506           prepare_record_for_error_message(error, table);
00507           table->print_error(error,MYF(flags));
00508           error= 1;
00509           break;
00510         }
00511       }
00512 
00513       if (!--limit && using_limit)
00514       {
00515         error= -1;        // Simulate end of cursor
00516         break;
00517       }
00518     }
00519     else
00520       table->cursor->unlock_row();
00521     session->row_count++;
00522   }
00523   dup_key_found= 0;
00524   /*
00525     Caching the killed status to pass as the arg to query event constuctor;
00526     The cached value can not change whereas the killed status can
00527     (externally) since this point and change of the latter won't affect
00528     binlogging.
00529     It's assumed that if an error was set in combination with an effective
00530     killed status then the error is due to killing.
00531   */
00532   killed_status= session->getKilled(); // get the status of the volatile
00533   // simulated killing after the loop must be ineffective for binlogging
00534   error= (killed_status == Session::NOT_KILLED)?  error : 1;
00535 
00536   updated-= dup_key_found;
00537   table->cursor->try_semi_consistent_read(0);
00538 
00539   if (!transactional_table && updated > 0)
00540     session->transaction.stmt.markModifiedNonTransData();
00541 
00542   info.end_read_record();
00543   delete select;
00544   session->set_proc_info("end");
00545   table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
00546 
00547   /*
00548     error < 0 means really no error at all: we processed all rows until the
00549     last one without error. error > 0 means an error (e.g. unique key
00550     violation and no IGNORE or REPLACE). error == 0 is also an error (if
00551     preparing the record or invoking before triggers fails). See
00552     autocommitOrRollback(error>=0) and return(error>=0) below.
00553     Sometimes we want to binlog even if we updated no rows, in case user used
00554     it to be sure master and slave are in same state.
00555   */
00556   if ((error < 0) || session->transaction.stmt.hasModifiedNonTransData())
00557   {
00558     if (session->transaction.stmt.hasModifiedNonTransData())
00559       session->transaction.all.markModifiedNonTransData();
00560   }
00561   assert(transactional_table || !updated || session->transaction.stmt.hasModifiedNonTransData());
00562   free_underlaid_joins(session, select_lex);
00563 
00564   /* If LAST_INSERT_ID(X) was used, report X */
00565   id= session->arg_of_last_insert_id_function ?
00566     session->first_successful_insert_id_in_prev_stmt : 0;
00567 
00568   if (error < 0)
00569   {
00570     char buff[STRING_BUFFER_USUAL_SIZE];
00571     snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
00572       (ulong) session->cuted_fields);
00573     session->row_count_func= updated;
00578     session->main_da().reset_diagnostics_area();
00579     session->my_ok((ulong) session->rowCount(), found, id, buff);
00580     session->status_var.updated_row_count+= session->rowCount();
00581   }
00582   session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;    /* calc cuted fields */
00583   session->setAbortOnWarning(false);
00584   DRIZZLE_UPDATE_DONE((error >= 0 || session->is_error()), found, updated);
00585   return ((error >= 0 || session->is_error()) ? 1 : 0);
00586 
00587 err:
00588   if (error != 0)
00589     table->print_error(error,MYF(0));
00590 
00591   delete select;
00592   free_underlaid_joins(session, select_lex);
00593   if (table->key_read)
00594   {
00595     table->key_read=0;
00596     table->cursor->extra(HA_EXTRA_NO_KEYREAD);
00597   }
00598   session->setAbortOnWarning(false);
00599 
00600   DRIZZLE_UPDATE_DONE(1, 0, 0);
00601   return 1;
00602 }
00603 
00604 /*
00605   Prepare items in UPDATE statement
00606 
00607   SYNOPSIS
00608     prepare_update()
00609     session     - thread handler
00610     table_list    - global/local table list
00611     conds   - conditions
00612     order_num   - number of ORDER BY list entries
00613     order   - ORDER BY clause list
00614 
00615   RETURN VALUE
00616     false OK
00617     true  error
00618 */
00619 bool prepare_update(Session *session, TableList *table_list,
00620        Item **conds, uint32_t order_num, Order *order)
00621 {
00622   List<Item> all_fields;
00623   Select_Lex *select_lex= &session->lex().select_lex;
00624 
00625   session->lex().allow_sum_func= 0;
00626 
00627   if (setup_tables_and_check_access(session, &select_lex->context, &select_lex->top_join_list, table_list, &select_lex->leaf_tables, false) ||
00628       session->setup_conds(table_list, conds))
00629       return true;
00630   select_lex->setup_ref_array(session, order_num);
00631   if (setup_order(session, select_lex->ref_pointer_array, table_list, all_fields, all_fields, order))
00632     return true;
00633 
00634   /* Check that we are not using table that we are updating in a sub select */
00635   if (unique_table(table_list, table_list->next_global))
00636   {
00637     my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->getTableName());
00638     return true;
00639   }
00640 
00641   return false;
00642 }
00643 
00644 } /* namespace drizzled */