#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)) != 00481 VIEW_CHECK_OK) 00482 { 00483 found--; 00484 if (res == VIEW_CHECK_SKIP) 00485 continue; 00486 else if (res == VIEW_CHECK_ERROR) 00487 { 00488 error= 1; 00489 break; 00490 } 00491 } 00492 if (will_batch) 00493 { 00494 /* 00495 Typically a batched handler can execute the batched jobs when: 00496 1) When specifically told to do so 00497 2) When it is not a good idea to batch anymore 00498 3) When it is necessary to send batch for other reasons 00499 (One such reason is when READ's must be performed) 00500 00501 1) is covered by exec_bulk_update calls. 00502 2) and 3) is handled by the bulk_update_row method. 00503 00504 bulk_update_row can execute the updates including the one 00505 defined in the bulk_update_row or not including the row 00506 in the call. This is up to the handler implementation and can 00507 vary from call to call. 00508 00509 The dup_key_found reports the number of duplicate keys found 00510 in those updates actually executed. It only reports those if 00511 the extra call with HA_EXTRA_IGNORE_DUP_KEY have been issued. 00512 If this hasn't been issued it returns an error code and can 00513 ignore this number. Thus any handler that implements batching 00514 for UPDATE IGNORE must also handle this extra call properly. 00515 00516 If a duplicate key is found on the record included in this 00517 call then it should be included in the count of dup_key_found 00518 and error should be set to 0 (only if these errors are ignored). 00519 */ 00520 error= table->file->bulk_update_row(table->record[1], 00521 table->record[0], 00522 &dup_key_found); 00523 limit+= dup_key_found; 00524 updated-= dup_key_found; 00525 } 00526 else 00527 { 00528 /* Non-batched update */ 00529 error= table->file->ha_update_row((byte*) table->record[1], 00530 (byte*) table->record[0]); 00531 } 00532 if (!error) 00533 { 00534 updated++; 00535 thd->no_trans_update= !transactional_table; 00536 00537 if (table->triggers && 00538 table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, 00539 TRG_ACTION_AFTER, TRUE)) 00540 { 00541 error= 1; 00542 break; 00543 } 00544 } 00545 else if (!ignore || 00546 table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) 00547 { 00548 /* 00549 If (ignore && error is ignorable) we don't have to 00550 do anything; otherwise... 00551 */ 00552 if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) 00553 thd->fatal_error(); /* Other handler errors are fatal */ 00554 table->file->print_error(error,MYF(0)); 00555 error= 1; 00556 break; 00557 } 00558 } 00559 00560 if (!--limit && using_limit) 00561 { 00562 /* 00563 We have reached end-of-file in most common situations where no 00564 batching has occurred and if batching was supposed to occur but 00565 no updates were made and finally when the batch execution was 00566 performed without error and without finding any duplicate keys. 00567 If the batched updates were performed with errors we need to 00568 check and if no error but duplicate key's found we need to 00569 continue since those are not counted for in limit. 00570 */ 00571 if (will_batch && 00572 ((error= table->file->exec_bulk_update(&dup_key_found)) || 00573 !dup_key_found)) 00574 { 00575 if (error) 00576 { 00577 /* 00578 The handler should not report error of duplicate keys if they 00579 are ignored. This is a requirement on batching handlers. 00580 */ 00581 table->file->print_error(error,MYF(0)); 00582 error= 1; 00583 break; 00584 } 00585 /* 00586 Either an error was found and we are ignoring errors or there 00587 were duplicate keys found. In both cases we need to correct 00588 the counters and continue the loop. 00589 */ 00590 limit= dup_key_found; //limit is 0 when we get here so need to + 00591 updated-= dup_key_found; 00592 } 00593 else 00594 { 00595 error= -1; // Simulate end of file 00596 break; 00597 } 00598 } 00599 } 00600 else 00601 table->file->unlock_row(); 00602 thd->row_count++; 00603 } 00604 dup_key_found= 0; 00605 if (thd->killed && !error) 00606 error= 1; // Aborted 00607 else if (will_batch && 00608 (loc_error= table->file->exec_bulk_update(&dup_key_found))) 00609 /* 00610 An error has occurred when a batched update was performed and returned 00611 an error indication. It cannot be an allowed duplicate key error since 00612 we require the batching handler to treat this as a normal behavior. 00613 00614 Otherwise we simply remove the number of duplicate keys records found 00615 in the batched update. 00616 */ 00617 { 00618 thd->fatal_error(); 00619 table->file->print_error(loc_error,MYF(0)); 00620 error= 1; 00621 } 00622 else 00623 updated-= dup_key_found; 00624 if (will_batch) 00625 table->file->end_bulk_update(); 00626 table->file->try_semi_consistent_read(0); 00627 end_read_record(&info); 00628 delete select; 00629 thd->proc_info= "end"; 00630 VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY)); 00631 00632 /* 00633 Invalidate the table in the query cache if something changed. 00634 This must be before binlog writing and ha_autocommit_... 00635 */ 00636 if (updated) 00637 { 00638 query_cache_invalidate3(thd, table_list, 1); 00639 } 00640 00641 /* 00642 error < 0 means really no error at all: we processed all rows until the 00643 last one without error. error > 0 means an error (e.g. unique key 00644 violation and no IGNORE or REPLACE). error == 0 is also an error (if 00645 preparing the record or invoking before triggers fails). See 00646 ha_autocommit_or_rollback(error>=0) and DBUG_RETURN(error>=0) below. 00647 Sometimes we want to binlog even if we updated no rows, in case user used 00648 it to be sure master and slave are in same state. 00649 */ 00650 if ((error < 0) || (updated && !transactional_table)) 00651 { 00652 if (mysql_bin_log.is_open()) 00653 { 00654 if (error < 0) 00655 thd->clear_error(); 00656 if (thd->binlog_query(THD::ROW_QUERY_TYPE, 00657 thd->query, thd->query_length, 00658 transactional_table, FALSE) && 00659 transactional_table) 00660 { 00661 error=1; // Rollback update 00662 } 00663 } 00664 if (!transactional_table) 00665 thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; 00666 } 00667 free_underlaid_joins(thd, select_lex); 00668 if (transactional_table) 00669 { 00670 if (ha_autocommit_or_rollback(thd, error >= 0)) 00671 error=1; 00672 } 00673 00674 if (thd->lock) 00675 { 00676 mysql_unlock_tables(thd, thd->lock); 00677 thd->lock=0; 00678 } 00679 00680 /* If LAST_INSERT_ID(X) was used, report X */ 00681 id= thd->arg_of_last_insert_id_function ? 00682 thd->first_successful_insert_id_in_prev_stmt : 0; 00683 00684 if (error < 0) 00685 { 00686 char buff[STRING_BUFFER_USUAL_SIZE]; 00687 sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, 00688 (ulong) thd->cuted_fields); 00689 thd->row_count_func= 00690 (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; 00691 send_ok(thd, (ulong) thd->row_count_func, id, buff); 00692 DBUG_PRINT("info",("%d records updated",updated)); 00693 } 00694 thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */ 00695 thd->abort_on_warning= 0; 00696 DBUG_RETURN((error >= 0 || thd->net.report_error) ? 1 : 0); 00697 00698 err: 00699 delete select; 00700 free_underlaid_joins(thd, select_lex); 00701 if (table->key_read) 00702 { 00703 table->key_read=0; 00704 table->file->extra(HA_EXTRA_NO_KEYREAD); 00705 } 00706 thd->abort_on_warning= 0; 00707 DBUG_RETURN(1); 00708 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1302 of file sql_update.cc.
References check_if_key_used(), QUICK_SELECT_I::check_if_keys_used(), FALSE, st_table::file, HA_PRIMARY_KEY_IN_READ_INDEX, handler::ha_table_flags(), Table_triggers_list::has_before_update_triggers(), JT_ALL, JT_CONST, JT_EQ_REF, JT_REF, JT_REF_OR_NULL, JT_SYSTEM, st_table_ref::key, MAX_KEY, st_table_share::primary_key, st_join_table::quick, st_join_table::ref, st_table::s, st_join_table::table, st_table::triggers, TRUE, and st_join_table::type.
01303 { 01304 TABLE *table= join_tab->table; 01305 switch (join_tab->type) { 01306 case JT_SYSTEM: 01307 case JT_CONST: 01308 case JT_EQ_REF: 01309 return TRUE; // At most one matching row 01310 case JT_REF: 01311 case JT_REF_OR_NULL: 01312 return !check_if_key_used(table, join_tab->ref.key, *fields) && 01313 !(table->triggers && 01314 table->triggers->has_before_update_triggers()); 01315 case JT_ALL: 01316 /* If range search on index */ 01317 if (join_tab->quick) 01318 return !join_tab->quick->check_if_keys_used(fields) && 01319 !(table->triggers && 01320 table->triggers->has_before_update_triggers()); 01321 /* If scanning in clustered key */ 01322 if ((table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && 01323 table->s->primary_key < MAX_KEY) 01324 return !check_if_key_used(table, table->s->primary_key, *fields) && 01325 !(table->triggers && 01326 table->triggers->has_before_update_triggers()); 01327 return TRUE; 01328 default: 01329 break; // Avoid compler warning 01330 } 01331 return FALSE; 01332 }
Here is the call graph for this function:

1.4.7

