The world's most popular open source database
#include "mysql_priv.h"#include "sql_select.h"#include "sp_head.h"#include "sql_trigger.h"Include dependency graph for sql_update.cc:

Go to the source code of this file.
Functions | |
| static bool | safe_update_on_fly (JOIN_TAB *join_tab, List< Item > *fields) |
| static bool | compare_record (TABLE *table) |
| static bool | check_fields (THD *thd, List< Item > &items) |
| int | mysql_update (THD *thd, TABLE_LIST *table_list, List< Item > &fields, List< Item > &values, COND *conds, uint order_num, ORDER *order, ha_rows limit, enum enum_duplicates handle_duplicates, bool ignore) |
| bool | mysql_prepare_update (THD *thd, TABLE_LIST *table_list, Item **conds, uint order_num, ORDER *order) |
| static table_map | get_table_map (List< Item > *items) |
| bool | mysql_multi_update_prepare (THD *thd) |
| bool | mysql_multi_update (THD *thd, TABLE_LIST *table_list, List< Item > *fields, List< Item > *values, COND *conds, ulonglong options, enum enum_duplicates handle_duplicates, bool ignore, SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex) |
Definition at line 65 of file sql_update.cc.
References ER_NONUPDATEABLE_COLUMN, FALSE, Item::filed_for_view_update(), my_error(), MYF, Item::name, List_iterator< T >::ref(), and TRUE.
00066 { 00067 List_iterator<Item> it(items); 00068 Item *item; 00069 Item_field *field; 00070 Name_resolution_context *context= &thd->lex->select_lex.context; 00071 00072 while ((item= it++)) 00073 { 00074 if (!(field= item->filed_for_view_update())) 00075 { 00076 /* item has name, because it comes from VIEW SELECT list */ 00077 my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name); 00078 return TRUE; 00079 } 00080 /* 00081 we make temporary copy of Item_field, to avoid influence of changing 00082 result_field on Item_ref which refer on this field 00083 */ 00084 thd->change_item_tree(it.ref(), new Item_field(thd, field)); 00085 } 00086 return FALSE; 00087 }
Here is the call graph for this function:

Definition at line 32 of file sql_update.cc.
References bitmap_is_set(), st_table_share::blob_fields, cmp_record, FALSE, st_table::field, memcmp(), st_table_share::null_bytes, st_table::null_flags, st_table_share::rec_buff_length, st_table::s, TRUE, st_table_share::varchar_fields, and st_table::write_set.
00033 { 00034 if (table->s->blob_fields + table->s->varchar_fields == 0) 00035 return cmp_record(table,record[1]); 00036 /* Compare null bits */ 00037 if (memcmp(table->null_flags, 00038 table->null_flags+table->s->rec_buff_length, 00039 table->s->null_bytes)) 00040 return TRUE; // Diff in NULL value 00041 /* Compare updated fields */ 00042 for (Field **ptr= table->field ; *ptr ; ptr++) 00043 { 00044 if (bitmap_is_set(table->write_set, (*ptr)->field_index) && 00045 (*ptr)->cmp_binary_offset(table->s->rec_buff_length)) 00046 return TRUE; 00047 } 00048 return FALSE; 00049 }
Here is the call graph for this function:

Definition at line 780 of file sql_update.cc.
References DBUG_PRINT, map, and Item_field::used_tables().
00781 { 00782 List_iterator_fast<Item> item_it(*items); 00783 Item_field *item; 00784 table_map map= 0; 00785 00786 while ((item= (Item_field *) item_it++)) 00787 map|= item->used_tables(); 00788 DBUG_PRINT("info",("table_map: 0x%08x", map)); 00789 return map; 00790 }
Here is the call graph for this function:

| bool mysql_multi_update | ( | THD * | thd, | |
| TABLE_LIST * | table_list, | |||
| List< Item > * | fields, | |||
| List< Item > * | values, | |||
| COND * | conds, | |||
| ulonglong | options, | |||
| enum enum_duplicates | handle_duplicates, | |||
| bool | ignore, | |||
| SELECT_LEX_UNIT * | unit, | |||
| SELECT_LEX * | select_lex | |||
| ) |
Definition at line 1011 of file sql_update.cc.
References DBUG_ENTER, DBUG_RETURN, FALSE, MODE_STRICT_ALL_TABLES, MODE_STRICT_TRANS_TABLES, mysql_select(), NULL, OPTION_SETUP_TABLES_DONE, st_table_list::select_lex, SELECT_NO_JOIN_CACHE, SELECT_NO_UNLOCK, test, and TRUE.
Referenced by mysql_execute_command().
01019 { 01020 multi_update *result; 01021 DBUG_ENTER("mysql_multi_update"); 01022 01023 if (!(result= new multi_update(table_list, 01024 thd->lex->select_lex.leaf_tables, 01025 fields, values, 01026 handle_duplicates, ignore))) 01027 DBUG_RETURN(TRUE); 01028 01029 thd->no_trans_update= 0; 01030 thd->abort_on_warning= test(thd->variables.sql_mode & 01031 (MODE_STRICT_TRANS_TABLES | 01032 MODE_STRICT_ALL_TABLES)); 01033 01034 List<Item> total_list; 01035 (void) mysql_select(thd, &select_lex->ref_pointer_array, 01036 table_list, select_lex->with_wild, 01037 total_list, 01038 conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL, 01039 (ORDER *)NULL, 01040 options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | 01041 OPTION_SETUP_TABLES_DONE, 01042 result, unit, select_lex); 01043 delete result; 01044 thd->abort_on_warning= 0; 01045 DBUG_RETURN(FALSE); 01046 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_multi_update_prepare | ( | THD * | thd | ) |
Definition at line 805 of file sql_update.cc.
References DBUG_ENTER, DBUG_RETURN, FALSE, MARK_COLUMNS_WRITE, mysql_derived_prepare(), mysql_handle_derived(), st_table_list::next_local, open_tables(), reopen_tables(), st_table_list::select_lex, setup_tables_and_check_access(), SQLCOM_UPDATE_MULTI, TRUE, UPDATE_ACL, and st_table_list::view.
00806 { 00807 LEX *lex= thd->lex; 00808 TABLE_LIST *table_list= lex->query_tables; 00809 TABLE_LIST *tl, *leaves; 00810 List<Item> *fields= &lex->select_lex.item_list; 00811 table_map tables_for_update; 00812 bool update_view= 0; 00813 /* 00814 if this multi-update was converted from usual update, here is table 00815 counter else junk will be assigned here, but then replaced with real 00816 count in open_tables() 00817 */ 00818 uint table_count= lex->table_count; 00819 const bool using_lock_tables= thd->locked_tables != 0; 00820 bool original_multiupdate= (thd->lex->sql_command == SQLCOM_UPDATE_MULTI); 00821 bool need_reopen= FALSE; 00822 DBUG_ENTER("mysql_multi_update_prepare"); 00823 00824 /* following need for prepared statements, to run next time multi-update */ 00825 thd->lex->sql_command= SQLCOM_UPDATE_MULTI; 00826 00827 reopen_tables: 00828 00829 /* open tables and create derived ones, but do not lock and fill them */ 00830 if (((original_multiupdate || need_reopen) && 00831 open_tables(thd, &table_list, &table_count, 0)) || 00832 mysql_handle_derived(lex, &mysql_derived_prepare)) 00833 DBUG_RETURN(TRUE); 00834 /* 00835 setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables() 00836 second time, but this call will do nothing (there are check for second 00837 call in setup_tables()). 00838 */ 00839 00840 if (setup_tables_and_check_access(thd, &lex->select_lex.context, 00841 &lex->select_lex.top_join_list, 00842 table_list, 00843 &lex->select_lex.leaf_tables, FALSE, 00844 UPDATE_ACL)) 00845 DBUG_RETURN(TRUE); 00846 00847 if (setup_fields_with_no_wrap(thd, 0, *fields, MARK_COLUMNS_WRITE, 0, 0)) 00848 DBUG_RETURN(TRUE); 00849 00850 for (tl= table_list; tl ; tl= tl->next_local) 00851 { 00852 if (tl->view) 00853 { 00854 update_view= 1; 00855 break; 00856 } 00857 } 00858 00859 if (update_view && check_fields(thd, *fields)) 00860 { 00861 DBUG_RETURN(TRUE); 00862 } 00863 00864 tables_for_update= get_table_map(fields); 00865 00866 /* 00867 Setup timestamp handling and locking mode 00868 */ 00869 leaves= lex->select_lex.leaf_tables; 00870 for (tl= leaves; tl; tl= tl->next_leaf) 00871 { 00872 TABLE *table= tl->table; 00873 /* Only set timestamp column if this is not modified */ 00874 if (table->timestamp_field && 00875 bitmap_is_set(table->write_set, 00876 table->timestamp_field->field_index)) 00877 table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; 00878 00879 /* if table will be updated then check that it is unique */ 00880 if (table->map & tables_for_update) 00881 { 00882 if (!tl->updatable || check_key_in_view(thd, tl)) 00883 { 00884 my_error(ER_NON_UPDATABLE_TABLE, MYF(0), tl->alias, "UPDATE"); 00885 DBUG_RETURN(TRUE); 00886 } 00887 00888 table->mark_columns_needed_for_update(); 00889 DBUG_PRINT("info",("setting table `%s` for update", tl->alias)); 00890 /* 00891 If table will be updated we should not downgrade lock for it and 00892 leave it as is. 00893 */ 00894 } 00895 else 00896 { 00897 DBUG_PRINT("info",("setting table `%s` for read-only", tl->alias)); 00898 /* 00899 If we are using the binary log, we need TL_READ_NO_INSERT to get 00900 correct order of statements. Otherwise, we use a TL_READ lock to 00901 improve performance. 00902 */ 00903 tl->lock_type= using_update_log ? TL_READ_NO_INSERT : TL_READ; 00904 tl->updating= 0; 00905 /* Update TABLE::lock_type accordingly. */ 00906 if (!tl->placeholder() && !tl->schema_table && !using_lock_tables) 00907 tl->table->reginfo.lock_type= tl->lock_type; 00908 } 00909 } 00910 for (tl= table_list; tl; tl= tl->next_local) 00911 { 00912 /* Check access privileges for table */ 00913 if (!tl->derived) 00914 { 00915 uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL; 00916 if (check_access(thd, want_privilege, 00917 tl->db, &tl->grant.privilege, 0, 0, 00918 test(tl->schema_table)) || 00919 (grant_option && check_grant(thd, want_privilege, tl, 0, 1, 0))) 00920 DBUG_RETURN(TRUE); 00921 } 00922 } 00923 00924 /* check single table update for view compound from several tables */ 00925 for (tl= table_list; tl; tl= tl->next_local) 00926 { 00927 if (tl->effective_algorithm == VIEW_ALGORITHM_MERGE) 00928 { 00929 TABLE_LIST *for_update= 0; 00930 if (tl->check_single_table(&for_update, tables_for_update, tl)) 00931 { 00932 my_error(ER_VIEW_MULTIUPDATE, MYF(0), 00933 tl->view_db.str, tl->view_name.str); 00934 DBUG_RETURN(-1); 00935 } 00936 } 00937 } 00938 00939 /* now lock and fill tables */ 00940 if (lock_tables(thd, table_list, table_count, &need_reopen)) 00941 { 00942 if (!need_reopen) 00943 DBUG_RETURN(TRUE); 00944 00945 /* 00946 We have to reopen tables since some of them were altered or dropped 00947 during lock_tables() or something was done with their triggers. 00948 Let us do some cleanups to be able do setup_table() and setup_fields() 00949 once again. 00950 */ 00951 List_iterator_fast<Item> it(*fields); 00952 Item *item; 00953 while ((item= it++)) 00954 item->cleanup(); 00955 00956 /* We have to cleanup translation tables of views. */ 00957 for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global) 00958 tbl->cleanup_items(); 00959 00960 close_tables_for_reopen(thd, &table_list); 00961 goto reopen_tables; 00962 } 00963 00964 /* 00965 Check that we are not using table that we are updating, but we should 00966 skip all tables of UPDATE SELECT itself 00967 */ 00968 lex->select_lex.exclude_from_table_unique_test= TRUE; 00969 /* We only need SELECT privilege for columns in the values list */ 00970 for (tl= leaves; tl; tl= tl->next_leaf) 00971 { 00972 TABLE *table= tl->table; 00973 TABLE_LIST *tlist; 00974 if (!(tlist= tl->top_table())->derived) 00975 { 00976 tlist->grant.want_privilege= 00977 (SELECT_ACL & ~tlist->grant.privilege); 00978 table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); 00979 } 00980 DBUG_PRINT("info", ("table: %s want_privilege: %u", tl->alias, 00981 (uint) table->grant.want_privilege)); 00982 if (tl->lock_type != TL_READ && 00983 tl->lock_type != TL_READ_NO_INSERT) 00984 { 00985 TABLE_LIST *duplicate; 00986 if ((duplicate= unique_table(thd, tl, table_list))) 00987 { 00988 update_non_unique_table_error(table_list, "UPDATE", duplicate); 00989 DBUG_RETURN(TRUE); 00990 } 00991 } 00992 } 00993 /* 00994 Set exclude_from_table_unique_test value back to FALSE. It is needed for 00995 further check in multi_update::prepare whether to use record cache. 00996 */ 00997 lex->select_lex.exclude_from_table_unique_test= FALSE; 00998 00999 if (thd->fill_derived_tables() && 01000 mysql_handle_derived(lex, &mysql_derived_filling)) 01001 DBUG_RETURN(TRUE); 01002 01003 DBUG_RETURN (FALSE); 01004 }
Here is the call graph for this function:

| bool mysql_prepare_update | ( | THD * | thd, | |
| TABLE_LIST * | table_list, | |||
| Item ** | conds, | |||
| uint | order_num, | |||
| ORDER * | order | |||
| ) |
Definition at line 725 of file sql_update.cc.
References st_table_list::alias, st_table::alias, bzero, DBUG_ENTER, DBUG_RETURN, ER_UPDATE_TABLE_USED, FALSE, st_table::grant, st_table_list::grant, my_error(), MYF, st_table_list::next_global, order, st_grant_info::privilege, st_table_list::register_want_access(), SELECT_ACL, setup_conds(), setup_ftfuncs(), setup_order(), setup_tables_and_check_access(), st_table_list::table, st_table_list::table_name, TRUE, unique_table(), UPDATE_ACL, update_non_unique_table_error(), and st_grant_info::want_privilege.
00727 { 00728 TABLE *table= table_list->table; 00729 TABLE_LIST tables; 00730 List<Item> all_fields; 00731 SELECT_LEX *select_lex= &thd->lex->select_lex; 00732 DBUG_ENTER("mysql_prepare_update"); 00733 00734 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00735 table_list->grant.want_privilege= table->grant.want_privilege= 00736 (SELECT_ACL & ~table->grant.privilege); 00737 table_list->register_want_access(SELECT_ACL); 00738 #endif 00739 00740 bzero((char*) &tables,sizeof(tables)); // For ORDER BY 00741 tables.table= table; 00742 tables.alias= table_list->alias; 00743 thd->lex->allow_sum_func= 0; 00744 00745 if (setup_tables_and_check_access(thd, &select_lex->context, 00746 &select_lex->top_join_list, 00747 table_list, 00748 &select_lex->leaf_tables, 00749 FALSE, UPDATE_ACL) || 00750 setup_conds(thd, table_list, select_lex->leaf_tables, conds) || 00751 select_lex->setup_ref_array(thd, order_num) || 00752 setup_order(thd, select_lex->ref_pointer_array, 00753 table_list, all_fields, all_fields, order) || 00754 setup_ftfuncs(select_lex)) 00755 DBUG_RETURN(TRUE); 00756 00757 /* Check that we are not using table that we are updating in a sub select */ 00758 { 00759 TABLE_LIST *duplicate; 00760 if ((duplicate= unique_table(thd, table_list, table_list->next_global))) 00761 { 00762 update_non_unique_table_error(table_list, "UPDATE", duplicate); 00763 my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name); 00764 DBUG_RETURN(TRUE); 00765 } 00766 } 00767 select_lex->fix_prepare_information(thd, conds); 00768 DBUG_RETURN(FALSE); 00769 }
Here is the call graph for this function:

| int mysql_update | ( | THD * | thd, | |
| TABLE_LIST * | table_list, | |||
| List< Item > & | fields, | |||
| List< Item > & | values, | |||
| COND * | conds, | |||
| uint | order_num, | |||
| ORDER * | order, | |||
| ha_rows | limit, | |||
| enum enum_duplicates | handle_duplicates, | |||
| bool | ignore | |||
| ) |
Definition at line 111 of file sql_update.cc.
References close_tables_for_reopen(), DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, error, HA_POS_ERROR, id, info, lock_tables, MAX_KEY, st_table_list::multitable_view, open_tables(), OPTION_SAFE_UPDATES, TRUE, updated, and st_table_list::view.
Referenced by mysql_execute_command().
00119 { 00120 bool using_limit= limit != HA_POS_ERROR; 00121 bool safe_update= thd->options & OPTION_SAFE_UPDATES; 00122 bool used_key_is_modified, transactional_table, will_batch; 00123 bool can_compare_record; 00124 int res; 00125 int error, loc_error; 00126 uint used_index= MAX_KEY, dup_key_found; 00127 bool need_sort= TRUE; 00128 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00129 uint want_privilege; 00130 #endif 00131 uint table_count= 0; 00132 ha_rows updated, found; 00133 key_map old_used_keys; 00134 TABLE *table; 00135 SQL_SELECT *select; 00136 READ_RECORD info; 00137 SELECT_LEX *select_lex= &thd->lex->select_lex; 00138 bool need_reopen; 00139 ulonglong id; 00140 DBUG_ENTER("mysql_update"); 00141 00142 for ( ; ; ) 00143 { 00144 if (open_tables(thd, &table_list, &table_count, 0)) 00145 DBUG_RETURN(1); 00146 00147 if (table_list->multitable_view) 00148 { 00149 DBUG_ASSERT(table_list->view != 0); 00150 DBUG_PRINT("info", ("Switch to multi-update")); 00151 /* pass counter value */ 00152 thd->lex->table_count= table_count; 00153 /* convert to multiupdate */ 00154 DBUG_RETURN(2); 00155 } 00156 if (!lock_tables(thd, table_list, table_count, &need_reopen)) 00157 break; 00158 if (!need_reopen) 00159 DBUG_RETURN(1); 00160 close_tables_for_reopen(thd, &table_list); 00161 } 00162 00163 if (mysql_handle_derived(thd->lex, &mysql_derived_prepare) || 00164 (thd->fill_derived_tables() && 00165 mysql_handle_derived(thd->lex, &mysql_derived_filling))) 00166 DBUG_RETURN(1); 00167 00168 thd->proc_info="init"; 00169 table= table_list->table; 00170 00171 /* Calculate "table->used_keys" based on the WHERE */ 00172 table->used_keys= table->s->keys_in_use; 00173 table->quick_keys.clear_all(); 00174 00175 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00176 /* TABLE_LIST contain right privilages request */ 00177 want_privilege= table_list->grant.want_privilege; 00178 #endif 00179 if (mysql_prepare_update(thd, table_list, &conds, order_num, order)) 00180 DBUG_RETURN(1); 00181 00182 old_used_keys= table->used_keys; // Keys used in WHERE 00183 /* Check the fields we are going to modify */ 00184 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00185 table_list->grant.want_privilege= table->grant.want_privilege= want_privilege; 00186 table_list->register_want_access(want_privilege); 00187 #endif 00188 if (setup_fields_with_no_wrap(thd, 0, fields, MARK_COLUMNS_WRITE, 0, 0)) 00189 DBUG_RETURN(1); /* purecov: inspected */ 00190 if (table_list->view && check_fields(thd, fields)) 00191 { 00192 DBUG_RETURN(1); 00193 } 00194 if (!table_list->updatable || check_key_in_view(thd, table_list)) 00195 { 00196 my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE"); 00197 DBUG_RETURN(1); 00198 } 00199 if (table->timestamp_field) 00200 { 00201 // Don't set timestamp column if this is modified 00202 if (bitmap_is_set(table->write_set, 00203 table->timestamp_field->field_index)) 00204 table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; 00205 else 00206 { 00207 bitmap_set_bit(table->write_set, 00208 table->timestamp_field->field_index); 00209 } 00210 } 00211 00212 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00213 /* Check values */ 00214 table_list->grant.want_privilege= table->grant.want_privilege= 00215 (SELECT_ACL & ~table->grant.privilege); 00216 #endif 00217 if (setup_fields(thd, 0, values, MARK_COLUMNS_READ, 0, 0)) 00218 { 00219 free_underlaid_joins(thd, select_lex); 00220 DBUG_RETURN(1); /* purecov: inspected */ 00221 } 00222 00223 if (conds) 00224 { 00225 Item::cond_result cond_value; 00226 conds= remove_eq_conds(thd, conds, &cond_value); 00227 if (cond_value == Item::COND_FALSE) 00228 limit= 0; // Impossible WHERE 00229 } 00230 // Don't count on usage of 'only index' when calculating which key to use 00231 table->used_keys.clear_all(); 00232 00233 #ifdef WITH_PARTITION_STORAGE_ENGINE 00234 if (prune_partitions(thd, table, conds)) 00235 { 00236 free_underlaid_joins(thd, select_lex); 00237 send_ok(thd); // No matching records 00238 DBUG_RETURN(0); 00239 } 00240 #endif 00241 /* Update the table->file->stats.records number */ 00242 table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); 00243 00244 select= make_select(table, 0, 0, conds, 0, &error); 00245 if (error || !limit || 00246 (select && select->check_quick(thd, safe_update, limit))) 00247 { 00248 delete select; 00249 free_underlaid_joins(thd, select_lex); 00250 if (error) 00251 { 00252 DBUG_RETURN(1); // Error in where 00253 } 00254 send_ok(thd); // No matching records 00255 DBUG_RETURN(0); 00256 } 00257 if (!select && limit != HA_POS_ERROR) 00258 { 00259 if ((used_index= get_index_for_order(table, order, limit)) != MAX_KEY) 00260 need_sort= FALSE; 00261 } 00262 /* If running in safe sql mode, don't allow updates without keys */ 00263 if (table->quick_keys.is_clear_all()) 00264 { 00265 thd->server_status|=SERVER_QUERY_NO_INDEX_USED; 00266 if (safe_update && !using_limit) 00267 { 00268 my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, 00269 ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0)); 00270 goto err; 00271 } 00272 } 00273 init_ftfuncs(thd, select_lex, 1); 00274 /* Check if we are modifying a key that we are used to search with */ 00275 00276 if (select && select->quick) 00277 { 00278 used_index= select->quick->index; 00279 used_key_is_modified= (!select->quick->unique_key_range() && 00280 select->quick->check_if_keys_used(&fields)); 00281 } 00282 else 00283 { 00284 used_key_is_modified= 0; 00285 if (used_index == MAX_KEY) // no index for sort order 00286 used_index= table->file->key_used_on_scan; 00287 if (used_index != MAX_KEY) 00288 used_key_is_modified= check_if_key_used(table, used_index, fields); 00289 } 00290 00291 #ifdef WITH_PARTITION_STORAGE_ENGINE 00292 if (used_key_is_modified || order || 00293 partition_key_modified(table, fields)) 00294 #else 00295 if (used_key_is_modified || order) 00296 #endif 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_used_keys.is_set(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 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 uint length; 00321 SORT_FIELD *sortorder; 00322 ha_rows examined_rows; 00323 00324 table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), 00325 MYF(MY_FAE | MY_ZEROFILL)); 00326 if (!(sortorder=make_unireg_sortorder(order, &length)) || 00327 (table->sort.found_records= filesort(thd, table, sortorder, length, 00328 select, limit, 1, 00329 &examined_rows)) 00330 == HA_POS_ERROR) 00331 { 00332 goto err; 00333 } 00334 /* 00335 Filesort has already found and selected the rows we want to update, 00336 so we don't need the where clause 00337 */ 00338 delete select; 00339 select= 0; 00340 } 00341 else 00342 { 00343 /* 00344 We are doing a search on a key that is updated. In this case 00345 we go trough the matching rows, save a pointer to them and 00346 update these in a separate loop based on the pointer. 00347 */ 00348 00349 IO_CACHE tempfile; 00350 if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX, 00351 DISK_BUFFER_SIZE, MYF(MY_WME))) 00352 goto err; 00353 00354 /* If quick select is used, initialize it before retrieving rows. */ 00355 if (select && select->quick && select->quick->reset()) 00356 goto err; 00357 table->file->try_semi_consistent_read(1); 00358 00359 /* 00360 When we get here, we have one of the following options: 00361 A. used_index == MAX_KEY 00362 This means we should use full table scan, and start it with 00363 init_read_record call 00364 B. used_index != MAX_KEY 00365 B.1 quick select is used, start the scan with init_read_record 00366 B.2 quick select is not used, this is full index scan (with LIMIT) 00367 Full index scan must be started with init_read_record_idx 00368 */ 00369 00370 if (used_index == MAX_KEY || (select && select->quick)) 00371 init_read_record(&info,thd,table,select,0,1); 00372 else 00373 init_read_record_idx(&info, thd, table, 1, used_index); 00374 00375 thd->proc_info="Searching rows for update"; 00376 uint tmp_limit= limit; 00377 00378 while (!(error=info.read_record(&info)) && !thd->killed) 00379 { 00380 if (!(select && select->skip_record())) 00381 { 00382 if (table->file->was_semi_consistent_read()) 00383 continue; /* repeat the read of the same row if it still exists */ 00384 00385 table->file->position(table->record[0]); 00386 if (my_b_write(&tempfile,table->file->ref, 00387 table->file->ref_length)) 00388 { 00389 error=1; /* purecov: inspected */ 00390 break; /* purecov: inspected */ 00391 } 00392 if (!--limit && using_limit) 00393 { 00394 error= -1; 00395 break; 00396 } 00397 } 00398 else 00399 table->file->unlock_row(); 00400 } 00401 if (thd->killed && !error) 00402 error= 1; // Aborted 00403 limit= tmp_limit; 00404 table->file->try_semi_consistent_read(0); 00405 end_read_record(&info); 00406 00407 /* Change select to use tempfile */ 00408 if (select) 00409 { 00410 delete select->quick; 00411 if (select->free_cond) 00412 delete select->cond; 00413 select->quick=0; 00414 select->cond=0; 00415 } 00416 else 00417 { 00418 select= new SQL_SELECT; 00419 select->head=table; 00420 } 00421 if (reinit_io_cache(&tempfile,READ_CACHE,0L,0,0)) 00422 error=1; /* purecov: inspected */ 00423 select->file=tempfile; // Read row ptrs from this file 00424 if (error >= 0) 00425 goto err; 00426 } 00427 if (table->key_read) 00428 table->restore_column_maps_after_mark_index(); 00429 } 00430 00431 if (ignore) 00432 table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); 00433 00434 if (select && select->quick && select->quick->reset()) 00435 goto err; 00436 table->file->try_semi_consistent_read(1); 00437 init_read_record(&info,thd,table,select,0,1); 00438 00439 updated= found= 0; 00440 thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */ 00441 thd->cuted_fields=0L; 00442 thd->proc_info="Updating"; 00443 00444 transactional_table= table->file->has_transactions(); 00445 thd->no_trans_update= 0; 00446 thd->abort_on_warning= test(!ignore && 00447 (thd->variables.sql_mode & 00448 (MODE_STRICT_TRANS_TABLES | 00449 MODE_STRICT_ALL_TABLES))); 00450 will_batch= !table->file->start_bulk_update(); 00451 00452 table->mark_columns_needed_for_update(); 00453 00454 /* 00455 We can use compare_record() to optimize away updates if 00456 the table handler is returning all columns OR if 00457 if all updated columns are read 00458 */ 00459 can_compare_record= (!(table->file->ha_table_flags() & 00460 HA_PARTIAL_COLUMN_READ) || 00461 bitmap_is_subset(table->write_set, table->read_set)); 00462 00463 while (!(error=info.read_record(&info)) && !thd->killed) 00464 { 00465 if (!(select && select->skip_record())) 00466 { 00467 if (table->file->was_semi_consistent_read()) 00468 continue; /* repeat the read of the same row if it still exists */ 00469 00470 store_record(table,record[1]); 00471 if (fill_record_n_invoke_before_triggers(thd, fields, values, 0, 00472 table->triggers, 00473 TRG_EVENT_UPDATE)) 00474 break; /* purecov: inspected */ 00475 00476 found++; 00477 00478 if (!can_compare_record || compare_record(table)) 00479 { 00480 if ((res= table_list->view_check_option(thd, ignore)

