REPLACE is defined as either INSERT or DELETE + INSERT. If possible, we can replace it with an UPDATE, but that will not work on InnoDB if FOREIGN KEY checks are necessary. Suppose that we got the duplicate key to be a key that is not the last unique key for the table and we perform an update: then there might be another key for which the unique check will fail, so we're better
| 2153 | actions |
| 2154 | */ |
| 2155 | int Write_record::replace_row(ha_rows *inserted, ha_rows *deleted) |
| 2156 | { |
| 2157 | int error; |
| 2158 | while (unlikely(error=table->file->ha_write_row(table->record[0]))) |
| 2159 | { |
| 2160 | error= prepare_handle_duplicate(error); |
| 2161 | if (unlikely(error)) |
| 2162 | return restore_on_error(); |
| 2163 | |
| 2164 | if (incomplete_records_cb && (error= incomplete_records_cb(arg1, arg2))) |
| 2165 | return restore_on_error(); |
| 2166 | |
| 2167 | if (can_optimize && key_nr == last_unique_key) |
| 2168 | { |
| 2169 | DBUG_PRINT("info", ("Updating row using ha_update_row()")); |
| 2170 | error= table->file->ha_update_row(table->record[1], table->record[0]); |
| 2171 | |
| 2172 | if (likely(!error)) |
| 2173 | { |
| 2174 | ++*deleted; |
| 2175 | if (table->versioned() && table->vers_write) |
| 2176 | { |
| 2177 | if (versioned) |
| 2178 | { |
| 2179 | store_record(table, record[2]); |
| 2180 | error= vers_insert_history_row(table); |
| 2181 | restore_record(table, record[2]); |
| 2182 | if (unlikely(error)) |
| 2183 | return on_ha_error(error); |
| 2184 | } |
| 2185 | ++*inserted; |
| 2186 | } |
| 2187 | } |
| 2188 | else if (error != HA_ERR_RECORD_IS_THE_SAME) |
| 2189 | return on_ha_error(error); |
| 2190 | break; |
| 2191 | } |
| 2192 | else |
| 2193 | { |
| 2194 | DBUG_PRINT("info", ("Deleting offending row and trying to write" |
| 2195 | " new one again")); |
| 2196 | |
| 2197 | auto *trg = table->triggers; |
| 2198 | bool trg_skip_row= false; |
| 2199 | if (use_triggers && trg->process_triggers(table->in_use, TRG_EVENT_DELETE, |
| 2200 | TRG_ACTION_BEFORE, true, |
| 2201 | &trg_skip_row)) |
| 2202 | return restore_on_error(); |
| 2203 | |
| 2204 | error= table->delete_row<true>(versioned); |
| 2205 | |
| 2206 | if (unlikely(error)) |
| 2207 | return on_ha_error(error); |
| 2208 | ++*deleted; |
| 2209 | |
| 2210 | if (use_triggers && !trg_skip_row) |
| 2211 | { |
| 2212 | error= trg->process_triggers(table->in_use, TRG_EVENT_DELETE, |
nothing calls this directly
no test coverage detected