12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
29
29
#include "drizzled/records.h"
30
30
#include "drizzled/internal/my_sys.h"
31
31
#include "drizzled/internal/iocache.h"
32
#include "drizzled/transaction_services.h"
33
#include "drizzled/filesort.h"
35
#include <boost/dynamic_bitset.hpp>
38
35
using namespace std;
46
43
If we got a duplicate key error, we want to write an error
47
44
message containing the value of the duplicate key. If we do not have
48
all fields of the key value in getInsertRecord(), we need to re-read the
45
all fields of the key value in record[0], we need to re-read the
49
46
record with a proper read_set.
51
48
@param[in] error error number
55
52
static void prepare_record_for_error_message(int error, Table *table)
57
Field **field_p= NULL;
57
MyBitmap unique_map; /* Fields in offended unique. */
58
my_bitmap_map unique_map_buf[bitmap_buffer_size(MAX_FIELDS)];
62
61
Only duplicate key errors print the key value.
63
62
If storage engine does always read all columns, we have the value alraedy.
65
64
if ((error != HA_ERR_FOUND_DUPP_KEY) ||
66
! (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ)))
65
!(table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ)))
76
75
/* Create unique_map with all fields used by that index. */
77
boost::dynamic_bitset<> unique_map(table->getShare()->sizeFields()); /* Fields in offended unique. */
78
table->mark_columns_used_by_index_no_reset(keynr, unique_map);
76
unique_map.init(unique_map_buf, table->getMutableShare()->sizeFields());
77
table->mark_columns_used_by_index_no_reset(keynr, &unique_map);
80
79
/* Subtract read_set and write_set. */
81
unique_map-= *table->read_set;
82
unique_map-= *table->write_set;
80
bitmap_subtract(&unique_map, table->read_set);
81
bitmap_subtract(&unique_map, table->write_set);
85
84
If the unique index uses columns that are neither in read_set
86
85
nor in write_set, we must re-read the record.
87
86
Otherwise no need to do anything.
89
if (unique_map.none())
88
if (unique_map.isClearAll())
92
91
/* Get identifier of last read record into table->cursor->ref. */
93
table->cursor->position(table->getInsertRecord());
92
table->cursor->position(table->record[0]);
94
93
/* Add all fields used by unique index to read_set. */
95
*table->read_set|= unique_map;
94
bitmap_union(table->read_set, &unique_map);
96
95
/* Read record that is identified by table->cursor->ref. */
97
(void) table->cursor->rnd_pos(table->getUpdateRecord(), table->cursor->ref);
96
(void) table->cursor->rnd_pos(table->record[1], table->cursor->ref);
98
97
/* Copy the newly read columns into the new record. */
99
for (field_p= table->getFields(); (field= *field_p); field_p++)
101
if (unique_map.test(field->position()))
98
for (field_p= table->field; (field= *field_p); field_p++)
99
if (unique_map.isBitSet(field->field_index))
103
100
field->copy_from_tmp(table->getShare()->rec_buff_length);
130
125
int mysql_update(Session *session, TableList *table_list,
131
126
List<Item> &fields, List<Item> &values, COND *conds,
132
uint32_t order_num, Order *order,
127
uint32_t order_num, order_st *order,
133
128
ha_rows limit, enum enum_duplicates,
136
131
bool using_limit= limit != HA_POS_ERROR;
137
132
bool used_key_is_modified;
138
133
bool transactional_table;
134
bool can_compare_record;
140
136
uint used_index= MAX_KEY, dup_key_found;
141
137
bool need_sort= true;
147
143
Select_Lex *select_lex= &session->lex->select_lex;
149
145
List<Item> all_fields;
150
Session::killed_state_t killed_status= Session::NOT_KILLED;
146
Session::killed_state killed_status= Session::NOT_KILLED;
152
DRIZZLE_UPDATE_START(session->getQueryString()->c_str());
148
DRIZZLE_UPDATE_START(session->query.c_str());
153
149
if (session->openTablesLock(table_list))
155
151
DRIZZLE_UPDATE_DONE(1, 0, 0);
164
160
table->quick_keys.reset();
166
162
if (mysql_prepare_update(session, table_list, &conds, order_num, order))
168
DRIZZLE_UPDATE_DONE(1, 0, 0);
172
165
old_covering_keys= table->covering_keys; // Keys used in WHERE
173
166
/* Check the fields we are going to modify */
174
167
if (setup_fields_with_no_wrap(session, 0, fields, MARK_COLUMNS_WRITE, 0, 0))
176
DRIZZLE_UPDATE_DONE(1, 0, 0);
180
169
if (table->timestamp_field)
182
171
// Don't set timestamp column if this is modified
183
172
if (table->timestamp_field->isWriteSet())
185
173
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
189
176
if (table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
190
177
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH)
192
table->setWriteSet(table->timestamp_field->position());
178
table->setWriteSet(table->timestamp_field->field_index);
197
182
if (setup_fields(session, 0, values, MARK_COLUMNS_READ, 0, 0))
199
184
free_underlaid_joins(session, select_lex);
200
DRIZZLE_UPDATE_DONE(1, 0, 0);
205
188
if (select_lex->inner_refs_list.elements &&
226
209
table->timestamp_field &&
227
210
(table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_UPDATE ||
228
211
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
230
*table->read_set|= *table->write_set;
212
bitmap_union(table->read_set, table->write_set);
232
213
// Don't count on usage of 'only index' when calculating which key to use
233
214
table->covering_keys.reset();
247
228
session->main_da.reset_diagnostics_area();
248
229
free_underlaid_joins(session, select_lex);
251
DRIZZLE_UPDATE_DONE(1, 0, 0);
231
goto abort; // Error in where
254
232
DRIZZLE_UPDATE_DONE(0, 0, 0);
255
233
session->my_ok(); // No matching records
282
260
if (used_index == MAX_KEY) // no index for sort order
283
261
used_index= table->cursor->key_used_on_scan;
284
262
if (used_index != MAX_KEY)
285
used_key_is_modified= is_key_used(table, used_index, *table->write_set);
263
used_key_is_modified= is_key_used(table, used_index, table->write_set);
311
289
NOTE: filesort will call table->prepare_for_position()
313
291
uint32_t length= 0;
314
SortField *sortorder;
292
SORT_FIELD *sortorder;
315
293
ha_rows examined_rows;
316
FileSort filesort(*session);
318
table->sort.io_cache= new internal::IO_CACHE;
295
table->sort.io_cache = new internal::IO_CACHE;
296
memset(table->sort.io_cache, 0, sizeof(internal::IO_CACHE));
320
298
if (!(sortorder=make_unireg_sortorder(order, &length, NULL)) ||
321
(table->sort.found_records= filesort.run(table, sortorder, length,
323
examined_rows)) == HA_POS_ERROR)
299
(table->sort.found_records= filesort(session, table, sortorder, length,
342
321
internal::IO_CACHE tempfile;
343
if (tempfile.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
322
if (open_cached_file(&tempfile, drizzle_tmpdir.c_str(),TEMP_PREFIX,
323
DISK_BUFFER_SIZE, MYF(MY_WME)))
348
326
/* If quick select is used, initialize it before retrieving rows. */
349
327
if (select && select->quick && select->quick->reset())
373
351
session->set_proc_info("Searching rows for update");
374
352
ha_rows tmp_limit= limit;
376
while (not(error= info.read_record(&info)) && not session->getKilled())
354
while (!(error=info.read_record(&info)) && !session->killed)
378
356
if (!(select && select->skip_record()))
380
358
if (table->cursor->was_semi_consistent_read())
381
359
continue; /* repeat the read of the same row if it still exists */
383
table->cursor->position(table->getInsertRecord());
361
table->cursor->position(table->record[0]);
384
362
if (my_b_write(&tempfile,table->cursor->ref,
385
363
table->cursor->ref_length))
416
394
select= new optimizer::SqlSelect;
417
395
select->head=table;
419
if (tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
397
if (reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
421
399
// Read row ptrs from this cursor
422
400
memcpy(select->file, &tempfile, sizeof(tempfile));
458
436
if (table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ))
459
437
table->prepare_for_position();
461
while (not (error=info.read_record(&info)) && not session->getKilled())
440
We can use compare_record() to optimize away updates if
441
the table handler is returning all columns OR if
442
if all updated columns are read
444
can_compare_record= (!(table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ)) ||
445
bitmap_is_subset(table->write_set, table->read_set));
447
while (!(error=info.read_record(&info)) && !session->killed)
463
if (not (select && select->skip_record()))
449
if (!(select && select->skip_record()))
465
451
if (table->cursor->was_semi_consistent_read())
466
452
continue; /* repeat the read of the same row if it still exists */
474
if (! table->records_are_comparable() || table->compare_records())
460
if (!can_compare_record || table->compare_record())
476
462
/* Non-batched update */
477
error= table->cursor->updateRecord(table->getUpdateRecord(),
478
table->getInsertRecord());
463
error= table->cursor->updateRecord(table->record[1],
480
466
table->auto_increment_field_not_null= false;
482
468
if (!error || error == HA_ERR_RECORD_IS_THE_SAME)
484
470
if (error != HA_ERR_RECORD_IS_THE_SAME)
490
476
table->cursor->is_fatal_error(error, HA_CHECK_DUP_KEY))
493
479
If (ignore && error is ignorable) we don't have to
494
480
do anything; otherwise...
499
485
flags|= ME_FATALERROR; /* Other handler errors are fatal */
501
487
prepare_record_for_error_message(error, table);
502
table->print_error(error,MYF(flags));
488
table->print_error(error,MYF(flags));
508
494
if (!--limit && using_limit)
524
510
It's assumed that if an error was set in combination with an effective
525
511
killed status then the error is due to killing.
527
killed_status= session->getKilled(); // get the status of the volatile
513
killed_status= session->killed; // get the status of the volatile
528
514
// simulated killing after the loop must be ineffective for binlogging
529
515
error= (killed_status == Session::NOT_KILLED)? error : 1;
573
559
session->main_da.reset_diagnostics_area();
574
560
session->my_ok((ulong) session->row_count_func, found, id, buff);
575
session->status_var.updated_row_count+= session->row_count_func;
577
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; /* calc cuted fields */
562
session->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
578
563
session->abort_on_warning= 0;
579
564
DRIZZLE_UPDATE_DONE((error >= 0 || session->is_error()), found, updated);
580
565
return ((error >= 0 || session->is_error()) ? 1 : 0);
611
597
bool mysql_prepare_update(Session *session, TableList *table_list,
612
Item **conds, uint32_t order_num, Order *order)
598
Item **conds, uint32_t order_num, order_st *order)
614
600
List<Item> all_fields;
615
601
Select_Lex *select_lex= &session->lex->select_lex;
632
618
TableList *duplicate;
633
619
if ((duplicate= unique_table(table_list, table_list->next_global)))
635
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->getTableName());
621
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);