00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "myisam_priv.h"
00019 #include <drizzled/util/test.h>
00020
00021 using namespace drizzled;
00022
00023 int mi_update(register MI_INFO *info, const unsigned char *oldrec, unsigned char *newrec)
00024 {
00025 int flag,key_changed,save_errno;
00026 register internal::my_off_t pos;
00027 uint32_t i;
00028 unsigned char old_key[MI_MAX_KEY_BUFF],*new_key;
00029 bool auto_key_changed=0;
00030 uint64_t changed;
00031 MYISAM_SHARE *share= info->s;
00032 internal::ha_checksum old_checksum= 0;
00033
00034 if (!(info->update & HA_STATE_AKTIV))
00035 {
00036 return(errno=HA_ERR_KEY_NOT_FOUND);
00037 }
00038 if (share->options & HA_OPTION_READ_ONLY_DATA)
00039 {
00040 return(errno=EACCES);
00041 }
00042 if (info->state->key_file_length >= share->base.margin_key_file_length)
00043 {
00044 return(errno=HA_ERR_INDEX_FILE_FULL);
00045 }
00046 pos=info->lastpos;
00047 if (_mi_readinfo(info,F_WRLCK,1))
00048 return(errno);
00049
00050 if (share->calc_checksum)
00051 old_checksum=info->checksum=(*share->calc_checksum)(info,oldrec);
00052 if ((*share->compare_record)(info,oldrec))
00053 {
00054 save_errno=errno;
00055 goto err_end;
00056 }
00057
00058
00059
00060 key_changed=0;
00061 for (i=0 ; i < share->state.header.uniques ; i++)
00062 {
00063 MI_UNIQUEDEF *def=share->uniqueinfo+i;
00064 if (mi_unique_comp(def, newrec, oldrec,1) &&
00065 mi_check_unique(info, def, newrec, mi_unique_hash(def, newrec),
00066 info->lastpos))
00067 {
00068 save_errno=errno;
00069 goto err_end;
00070 }
00071 }
00072 if (_mi_mark_file_changed(info))
00073 {
00074 save_errno=errno;
00075 goto err_end;
00076 }
00077
00078
00079
00080 new_key=info->lastkey2;
00081 changed=0;
00082 for (i=0 ; i < share->base.keys ; i++)
00083 {
00084 if (mi_is_key_active(share->state.key_map, i))
00085 {
00086 {
00087 uint32_t new_length=_mi_make_key(info,i,new_key,newrec,pos);
00088 uint32_t old_length=_mi_make_key(info,i,old_key,oldrec,pos);
00089
00090
00091 info->update&= ~HA_STATE_RNEXT_SAME;
00092
00093 if (new_length != old_length ||
00094 memcmp(old_key,new_key,new_length))
00095 {
00096 if ((int) i == info->lastinx)
00097 key_changed|=HA_STATE_WRITTEN;
00098 changed|=((uint64_t) 1 << i);
00099 share->keyinfo[i].version++;
00100 if (share->keyinfo[i].ck_delete(info,i,old_key,old_length)) goto err;
00101 if (share->keyinfo[i].ck_insert(info,i,new_key,new_length)) goto err;
00102 if (share->base.auto_key == i+1)
00103 auto_key_changed=1;
00104 }
00105 }
00106 }
00107 }
00108
00109
00110
00111
00112 if (changed)
00113 key_changed|= HA_STATE_CHANGED;
00114
00115 if (share->calc_checksum)
00116 {
00117 info->checksum=(*share->calc_checksum)(info,newrec);
00118
00119 key_changed|= HA_STATE_CHANGED;
00120 }
00121 {
00122
00123
00124
00125
00126 MI_STATUS_INFO state;
00127 ha_rows org_split;
00128 internal::my_off_t org_delete_link;
00129
00130 memcpy(&state, info->state, sizeof(state));
00131 org_split= share->state.split;
00132 org_delete_link= share->state.dellink;
00133 if ((*share->update_record)(info,pos,newrec))
00134 goto err;
00135 if (!key_changed &&
00136 (memcmp(&state, info->state, sizeof(state)) ||
00137 org_split != share->state.split ||
00138 org_delete_link != share->state.dellink))
00139 key_changed|= HA_STATE_CHANGED;
00140 }
00141 if (auto_key_changed)
00142 set_if_bigger(info->s->state.auto_increment,
00143 retrieve_auto_increment(info, newrec));
00144 if (share->calc_checksum)
00145 info->state->checksum+=(info->checksum - old_checksum);
00146
00147 info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV |
00148 key_changed);
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 _mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE);
00160 return(0);
00161
00162 err:
00163 save_errno=errno;
00164 if (changed)
00165 key_changed|= HA_STATE_CHANGED;
00166 if (errno == HA_ERR_FOUND_DUPP_KEY || errno == HA_ERR_OUT_OF_MEM ||
00167 errno == HA_ERR_RECORD_FILE_FULL)
00168 {
00169 info->errkey= (int) i;
00170 flag=0;
00171 do
00172 {
00173 if (((uint64_t) 1 << i) & changed)
00174 {
00175 {
00176 uint32_t new_length=_mi_make_key(info,i,new_key,newrec,pos);
00177 uint32_t old_length= _mi_make_key(info,i,old_key,oldrec,pos);
00178 if ((flag++ && _mi_ck_delete(info,i,new_key,new_length)) ||
00179 _mi_ck_write(info,i,old_key,old_length))
00180 break;
00181 }
00182 }
00183 } while (i-- != 0);
00184 }
00185 else
00186 {
00187 mi_print_error(info->s, HA_ERR_CRASHED);
00188 mi_mark_crashed(info);
00189 }
00190 info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_ROW_CHANGED |
00191 key_changed);
00192
00193 err_end:
00194 _mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE);
00195 if (save_errno == HA_ERR_KEY_NOT_FOUND)
00196 {
00197 mi_print_error(info->s, HA_ERR_CRASHED);
00198 save_errno=HA_ERR_CRASHED;
00199 }
00200 return(errno=save_errno);
00201 }